diff options
4 files changed, 182 insertions, 79 deletions
diff --git a/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/base/util/ImportHelpers.java b/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/base/util/ImportHelpers.java new file mode 100644 index 000000000..df0354686 --- /dev/null +++ b/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/base/util/ImportHelpers.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Juergen Haug (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.core.common.base.util; + +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.etrice.core.common.base.Import; +import org.eclipse.xtext.naming.IQualifiedNameConverter; +import org.eclipse.xtext.naming.QualifiedName; +import org.eclipse.xtext.resource.IEObjectDescription; +import org.eclipse.xtext.resource.IResourceDescription; +import org.eclipse.xtext.resource.IResourceServiceProvider; +import org.eclipse.xtext.scoping.impl.ImportUriResolver; + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; + +public class ImportHelpers { + + /** + * Returns a list of imported target eObjects for an import or absent if import is not computable. + * The list contains either a single exact match (name and quickFixCandidateMatcher) or candidates (name + * or quickFixCandidateMatcher) or empty. + */ + public static Optional<List<IEObjectDescription>> getImportedObjectsFor(Import imp, ImportUriResolver importUriResolver, + Predicate<IEObjectDescription> quickFixCandidateMatcher) { + + QualifiedName importedFQN = toFQN(imp); + if (importedFQN == null) + return Optional.empty(); + + // check in BaseJavaValidator.checkImportURI + String uriString = importUriResolver.resolve(imp); + if (uriString == null) + return Optional.empty(); + + URI uri = URI.createURI(uriString); + Resource importedResource = null; + try { + importedResource = imp.eResource().getResourceSet().getResource(uri, true); + } catch (RuntimeException re) { + return Optional.empty(); + } + IResourceServiceProvider resourceServiceProvider = IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(uri); + if (importedResource == null || resourceServiceProvider == null) + return Optional.empty(); + IResourceDescription.Manager manager = resourceServiceProvider.getResourceDescriptionManager(); + IResourceDescription description = manager.getResourceDescription(importedResource); + + List<IEObjectDescription> candidates = Lists.newArrayList(); + if (description != null) { + Iterator<IEObjectDescription> iter = description.getExportedObjects().iterator(); + while (iter.hasNext()) { + IEObjectDescription eObjDesc = iter.next(); + if (importedFQN.equals(eObjDesc.getQualifiedName())) { + if (quickFixCandidateMatcher.apply(eObjDesc)) { + // exact match -> early quit + return Optional.of(Lists.newArrayList(eObjDesc)); + } + candidates.add(eObjDesc); + } else if (quickFixCandidateMatcher.apply(eObjDesc)) { + candidates.add(eObjDesc); + } + } + } + + return Optional.of(candidates); + } + + public static QualifiedName toFQN(Import imp) { + IQualifiedNameConverter nameConverter = new IQualifiedNameConverter.DefaultImpl(); + boolean isWildcard = false; + try { + QualifiedName orig = nameConverter.toQualifiedName(imp.getImportedNamespace()); + isWildcard = orig.getLastSegment().equals("*"); + return (isWildcard) ? orig.skipLast(1) : orig; + } catch(IllegalArgumentException e){ + return null; + } + } +} diff --git a/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/validation/BaseJavaValidator.java b/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/validation/BaseJavaValidator.java index 791cf77df..072e31342 100644 --- a/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/validation/BaseJavaValidator.java +++ b/plugins/org.eclipse.etrice.core.common/src/org/eclipse/etrice/core/common/validation/BaseJavaValidator.java @@ -15,6 +15,9 @@ package org.eclipse.etrice.core.common.validation; import java.util.HashSet; import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.etrice.core.common.base.Annotation; import org.eclipse.etrice.core.common.base.AnnotationAttribute; import org.eclipse.etrice.core.common.base.AnnotationType; @@ -22,13 +25,17 @@ import org.eclipse.etrice.core.common.base.BasePackage; import org.eclipse.etrice.core.common.base.BooleanLiteral; import org.eclipse.etrice.core.common.base.Documentation; import org.eclipse.etrice.core.common.base.EnumAnnotationAttribute; +import org.eclipse.etrice.core.common.base.Import; import org.eclipse.etrice.core.common.base.IntLiteral; import org.eclipse.etrice.core.common.base.KeyValue; import org.eclipse.etrice.core.common.base.RealLiteral; import org.eclipse.etrice.core.common.base.SimpleAnnotationAttribute; import org.eclipse.etrice.core.common.base.StringLiteral; +import org.eclipse.xtext.scoping.impl.ImportUriResolver; import org.eclipse.xtext.validation.Check; +import com.google.inject.Inject; + /** * Custom validation rules. * @@ -42,6 +49,8 @@ public class BaseJavaValidator extends org.eclipse.etrice.core.common.validation public static final String UNDEFINED_ANNOTATION_ATTRIBUTE_VALUE = "BaseJavaValidator.UndfinedAnnotationAttributeValue"; public static final String DUPLICATE_ANNOTATION_ATTRIBUTE = "BaseJavaValidator.DuplicateAnnotationAttribute"; + @Inject ImportUriResolver importUriResolver; + @Check public void checkDocumentation(Documentation doc) { if (doc.getLines().isEmpty()) @@ -169,4 +178,32 @@ public class BaseJavaValidator extends org.eclipse.etrice.core.common.validation } } } + + @Check + public void checkImportedURI(Import imp) { + String uriString = importUriResolver.resolve(imp); + if (uriString == null) { + warning("could not load referenced model", BasePackage.Literals.IMPORT__IMPORT_URI); + return; + } + + URI uri = URI.createURI(uriString); + ResourceSet rs = imp.eResource().getResourceSet(); + + try { + Resource importedResource = rs.getResource(uri, true); + if (importedResource == null) + return; + + if (importedResource.getContents().isEmpty()) { + // importedResource is empty after being loaded the first time (<=> RuntimeException below) + warning("could not load referenced model", BasePackage.Literals.IMPORT__IMPORT_URI); + return; + } + } catch (RuntimeException re) { + warning("could not load referenced model", BasePackage.Literals.IMPORT__IMPORT_URI); + return; + } + } + } diff --git a/plugins/org.eclipse.etrice.core.fsm.ui/src/org/eclipse/etrice/core/fsm/ui/quickfix/FSMQuickfixProvider.xtend b/plugins/org.eclipse.etrice.core.fsm.ui/src/org/eclipse/etrice/core/fsm/ui/quickfix/FSMQuickfixProvider.xtend index 8b842d9d2..498bc4c68 100644 --- a/plugins/org.eclipse.etrice.core.fsm.ui/src/org/eclipse/etrice/core/fsm/ui/quickfix/FSMQuickfixProvider.xtend +++ b/plugins/org.eclipse.etrice.core.fsm.ui/src/org/eclipse/etrice/core/fsm/ui/quickfix/FSMQuickfixProvider.xtend @@ -4,22 +4,22 @@ package org.eclipse.etrice.core.fsm.ui.quickfix import com.google.inject.Inject +import org.eclipse.etrice.core.common.converter.BaseConverterService +import org.eclipse.etrice.core.common.ui.quickfix.BaseQuickfixProvider import org.eclipse.etrice.core.fsm.fSM.DetailCode import org.eclipse.etrice.core.fsm.validation.FSMJavaValidator import org.eclipse.xtext.formatting.IWhitespaceInformationProvider import org.eclipse.xtext.nodemodel.util.NodeModelUtils -import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider import org.eclipse.xtext.ui.editor.quickfix.Fix import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor import org.eclipse.xtext.validation.Issue -import org.eclipse.etrice.core.common.converter.BaseConverterService /** * Custom quickfixes. * * see http://www.eclipse.org/Xtext/documentation.html#quickfixes */ -class FSMQuickfixProvider extends DefaultQuickfixProvider { +class FSMQuickfixProvider extends BaseQuickfixProvider { @Inject BaseConverterService converterService diff --git a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java index cf6f2a6b5..0d5c04a5e 100644 --- a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java +++ b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java @@ -16,22 +16,20 @@ package org.eclipse.etrice.core.validation; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.etrice.core.common.base.Annotation; import org.eclipse.etrice.core.common.base.BasePackage; import org.eclipse.etrice.core.common.base.Import; import org.eclipse.etrice.core.common.base.LiteralType; +import org.eclipse.etrice.core.common.base.util.ImportHelpers; import org.eclipse.etrice.core.common.validation.ValidationHelpers; import org.eclipse.etrice.core.common.validation.ValidationHelpers.NamedObject; import org.eclipse.etrice.core.common.validation.ValidationHelpers.NamedObjectList; @@ -64,24 +62,22 @@ import org.eclipse.etrice.core.room.RefPath; import org.eclipse.etrice.core.room.ReferenceType; import org.eclipse.etrice.core.room.RoomAnnotationTargetEnum; import org.eclipse.etrice.core.room.RoomClass; -import org.eclipse.etrice.core.room.RoomModel; import org.eclipse.etrice.core.room.RoomPackage; import org.eclipse.etrice.core.room.ServiceImplementation; import org.eclipse.etrice.core.room.StandardOperation; import org.eclipse.etrice.core.room.StructureClass; import org.eclipse.etrice.core.room.SubSystemClass; import org.eclipse.etrice.core.room.util.RoomHelpers; -import org.eclipse.xtext.naming.IQualifiedNameConverter; import org.eclipse.xtext.naming.IQualifiedNameProvider; import org.eclipse.xtext.naming.QualifiedName; import org.eclipse.xtext.resource.IEObjectDescription; -import org.eclipse.xtext.resource.IResourceDescription; -import org.eclipse.xtext.resource.IResourceServiceProvider; import org.eclipse.xtext.scoping.impl.ImportUriResolver; import org.eclipse.xtext.validation.Check; import com.google.common.base.Function; -import com.google.common.collect.Lists; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.inject.Inject; @@ -95,6 +91,8 @@ public class RoomJavaValidator extends AbstractRoomJavaValidator { @Inject protected ValidationUtil validationUtil; @Inject protected IQualifiedNameProvider fqnProvider; + + @Inject ImportUriResolver importUriResolver; /* message strings */ public static final String OPTIONAL_REFS_HAVE_TO_HAVE_MULTIPLICITY_ANY = "optional refs have to have multiplicity any [*]"; @@ -104,94 +102,67 @@ public class RoomJavaValidator extends AbstractRoomJavaValidator { /* tags for quick fixes */ public static final String THREAD_MISSING = "RoomJavaValidator.ThreadMissing"; public static final String DUPLICATE_ACTOR_INSTANCE_MAPPING = "RoomJavaValidator.DuplicateActorInstanceMapping"; - public static final String WRONG_NAMESPACE = "RoomJavaValidator.WrongNamespace"; public static final String CIRCULAR_CONTAINMENT = "RoomJavaValidator.CircularContainment"; public static final String ACTOR_REF_CHANGE_REF_TYPE_TO_FIXED_OR_MULT_TO_ANY = "RoomJavaValidator.ActorRefChangeRefTypeToFixed"; public static final String ACTOR_REF_CHANGE_REF_TYPE_TO_OPTIONAL = "RoomJavaValidator.ActorRefChangeRefTypeToOptional"; + public static final String WRONG_NAMESPACE = "RoomJavaValidator.WrongNamespace"; public static final String CHANGE_DESTRUCTOR_NAME = "RoomJavaValidator.ChangeDestructorName"; public static final String CHANGE_CONSTRUCTOR_NAME = "RoomJavaValidator.ChangeConstructorName"; public static final String INVALID_ANNOTATION_TARGET = "RoomJavaValidator.InvalidAnnotationTarget"; public static final String OPERATION_MISSING_OVERRIDE = "RoomJavaValidator.OperationMissingOverride"; public static final String OPERATION_EXTRANEOUS_OVERRIDE = "RoomJavaValidator.OperationExtraneousOverride"; - public static final String INCONSISTENT_COMMUNICATION_TYPE = "RoomJavaValidator.InconsistentCommType"; - - @Inject ImportUriResolver importUriResolver; + public static final String INCONSISTENT_COMMUNICATION_TYPE = "RoomJavaValidator.InconsistentCommType"; @Check - public void checkImportedNamespace(Import imp) { - if (imp.getImportURI()==null) - return; - - IQualifiedNameConverter nameConverter = new IQualifiedNameConverter.DefaultImpl(); - QualifiedName importedFQN; - boolean isWildcard = false; - try { - QualifiedName orig = nameConverter.toQualifiedName(imp.getImportedNamespace()); - isWildcard = orig.getLastSegment().equals("*"); - importedFQN = (isWildcard) ? orig.skipLast(1) : orig; - } catch(IllegalArgumentException e){ + public void checkRoomImportedNamespace(Import imp) { + QualifiedName importedFQN = ImportHelpers.toFQN(imp); + if(importedFQN == null) return; - } - - String uriString = importUriResolver.resolve(imp); - if(uriString == null) { - warning("could not load referenced model", BasePackage.Literals.IMPORT__IMPORT_URI); - return; - } - - URI uri = URI.createURI(uriString); - ResourceSet rs = imp.eResource().getResourceSet(); - - List<RoomModel> importedModels = Lists.newArrayList(); - try { - Resource res = rs.getResource(uri, true); - if (res==null) - return; + + Predicate<IEObjectDescription> nameMatcher = new Predicate<IEObjectDescription>() { - if (res.getContents().isEmpty()) { - error("referenced model is empty", BasePackage.Literals.IMPORT__IMPORT_URI); - return; + @Override + public boolean apply(IEObjectDescription input) { + return importedFQN.equals(input.getQualifiedName()); } + + }; + Predicate<IEObjectDescription> candidateMatcher = new Predicate<IEObjectDescription>() { - for(EObject content : res.getContents()) { - if(content instanceof RoomModel) { - importedModels.add((RoomModel) content); - } + @Override + public boolean apply(IEObjectDescription input) { + return input.getEClass() == RoomPackage.Literals.ROOM_MODEL; } - if (importedModels.isEmpty()) { - if (uri.fileExtension().equals("room")) - error("referenced model is no ROOM model (but has .room extension)", BasePackage.Literals.IMPORT__IMPORT_URI); - else - warning("referenced model is no ROOM model", BasePackage.Literals.IMPORT__IMPORT_URI); - return; + }; + Predicate<IEObjectDescription> allowedClasses = new Predicate<IEObjectDescription>() { + + @Override + public boolean apply(IEObjectDescription input) { + return input.getEClass() == RoomPackage.Literals.ROOM_MODEL || + RoomPackage.Literals.ROOM_CLASS.isSuperTypeOf(input.getEClass()); } - } - catch (RuntimeException re) { - warning("could not load referenced model", BasePackage.Literals.IMPORT__IMPORT_URI); + + }; + Optional<List<IEObjectDescription>> importCandidates = ImportHelpers.getImportedObjectsFor(imp, importUriResolver, candidateMatcher); + if(!importCandidates.isPresent()) return; - } - - final IResourceServiceProvider resourceServiceProvider = IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(uri); - if (resourceServiceProvider==null) + + List<IEObjectDescription> candidates = importCandidates.get(); + if(Iterables.any(candidates, Predicates.and(nameMatcher, candidateMatcher))) return; - IResourceDescription.Manager manager = resourceServiceProvider.getResourceDescriptionManager(); - IResourceDescription description = manager.getResourceDescription(importedModels.get(0).eResource()); - - // TODO check for empty namespace - boolean exportedNameMatch = false; - if (description != null) { - Iterator<IEObjectDescription> iter = description.getExportedObjects().iterator(); - while(iter.hasNext()){ - QualifiedName exportedFQN = iter.next().getQualifiedName(); - if(exportedNameMatch |= importedFQN.equals(exportedFQN)) - break; - } - } - if(!exportedNameMatch) { - error("no match for imported namespace", BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, WRONG_NAMESPACE, importedModels.get(0).getName()+".*"); + + Set<String> candidatesNames = Sets.newLinkedHashSet(); + for(IEObjectDescription eObjDesc : candidates) { + candidatesNames.add(eObjDesc.getQualifiedName().toString() + ".*"); } + + if(!Iterables.any(candidates, nameMatcher)) + error("no match for imported namespace", BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, WRONG_NAMESPACE, candidatesNames.toArray(new String[0])); + else if(!Iterables.any(Iterables.filter(candidates, nameMatcher), allowedClasses)) + error("referenced model is not supported", BasePackage.Literals.IMPORT__IMPORTED_NAMESPACE, WRONG_NAMESPACE, candidatesNames.toArray(new String[0])); } + @Check public void checkActorRef(ActorRef ar) { |