diff --git a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/SadlLinkingTest.xtend b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/SadlLinkingTest.xtend index 1400ed9e5..5c5f12b3f 100644 --- a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/SadlLinkingTest.xtend +++ b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/SadlLinkingTest.xtend @@ -1133,7 +1133,7 @@ class SadlLinkingTest extends AbstractLinkingTest { @Test def void testImportPerformance() { - for (i : 99 .. 100) { + for (i : 1 .. 19) { val started = Stopwatch.createStarted val resource = ''' uri "http://sadl.org/NS1.sadl«i»" alias ns«i». diff --git a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/ScopingTest.xtend b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/ScopingTest.xtend index c087ff114..f0ca8ee97 100644 --- a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/ScopingTest.xtend +++ b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl.tests/src/com/ge/research/sadl/tests/scoping/ScopingTest.xtend @@ -177,7 +177,7 @@ class ScopingTest { described by when with values of type dateTime, described by openingEvent with a single value of type Event, described by closingEvent with a single value of type Event. - + Circus is a class, described by event with values of type Event. @@ -199,19 +199,5 @@ class ScopingTest { ] } - - @Test def void testScopingSlowdown() { - for (i:1 ..< 10) { - var modeltext = "uri \"http://com.ge.research.sadl/scopingscaletest\".\n" - for (j:0 ..< i*100) { - modeltext += "Pr" + j + " is a property.\n" - } -// print(modeltext) - var t1 = System.currentTimeMillis - var model = modeltext.parse - validationTestHelper.assertNoErrors(model.eResource) - var t2 = System.currentTimeMillis; - print(i*100 + "," + (t2-t1) + "ms\n") - } - } + } \ No newline at end of file diff --git a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/processing/SadlModelProcessorProvider.xtend b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/processing/SadlModelProcessorProvider.xtend index f98526179..0d9e48911 100644 --- a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/processing/SadlModelProcessorProvider.xtend +++ b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/processing/SadlModelProcessorProvider.xtend @@ -26,9 +26,6 @@ import org.eclipse.xtend.lib.annotations.Data import org.eclipse.xtext.generator.IFileSystemAccess2 import org.eclipse.xtext.util.OnChangeEvictingCache import org.eclipse.xtext.validation.CheckMode -import com.ge.research.sadl.processing.IModelProcessor.ProcessorContext -import org.eclipse.xtext.util.IAcceptor -import com.ge.research.sadl.builder.MessageManager.SadlMessage class SadlModelProcessorProvider implements IModelProcessorProvider { diff --git a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/ErrorAddingLinkingService.java b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/ErrorAddingLinkingService.java index dc1aeb537..e753a0fca 100644 --- a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/ErrorAddingLinkingService.java +++ b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/ErrorAddingLinkingService.java @@ -17,7 +17,6 @@ import org.eclipse.xtext.resource.IEObjectDescription; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.IScopeProvider; -import org.eclipse.xtext.scoping.impl.MapBasedScope; import com.google.inject.Inject; @@ -67,19 +66,6 @@ public List getLinkedObjects(EObject context, EReference ref, INode nod return Collections.emptyList(); } -// protected IScope getScope(EObject context, EReference ref) { -// Resource rsrc = context.eResource(); -// IScope scope = TestScopeProvider.find(rsrc); -// if (scope == null) { -// scope = super.getScope(context, ref); -// if (scope instanceof MapBasedScope) { -// TestScopeProvider.attach(rsrc, scope); -//// System.out.println("Attaching scope to '" + rsrc.toString() + "': " + scope.toString()); -// } -// } -// return scope; -// } - protected void createAndAddDiagnostic(Resource resource, INode node, String message, String commaSeparatedAlternatives) { resource.getErrors().add(new XtextLinkingDiagnostic(node, message, ISSUE_CODE, commaSeparatedAlternatives)); } diff --git a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/SADLScopeProvider.xtend b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/SADLScopeProvider.xtend index 7db27f309..796ac9c41 100644 --- a/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/SADLScopeProvider.xtend +++ b/sadl3/com.ge.research.sadl.parent/com.ge.research.sadl/src/com/ge/research/sadl/scoping/SADLScopeProvider.xtend @@ -25,18 +25,20 @@ import com.ge.research.sadl.sADL.BinaryOperation import com.ge.research.sadl.sADL.EquationStatement import com.ge.research.sadl.sADL.Expression import com.ge.research.sadl.sADL.PropOfSubject +import com.ge.research.sadl.sADL.QueryStatement import com.ge.research.sadl.sADL.RuleStatement import com.ge.research.sadl.sADL.SADLPackage import com.ge.research.sadl.sADL.SadlClassOrPropertyDeclaration import com.ge.research.sadl.sADL.SadlImport +import com.ge.research.sadl.sADL.SadlInstance import com.ge.research.sadl.sADL.SadlModel import com.ge.research.sadl.sADL.SadlMustBeOneOf import com.ge.research.sadl.sADL.SadlProperty import com.ge.research.sadl.sADL.SadlResource import com.ge.research.sadl.sADL.SubjHasProp +import com.ge.research.sadl.sADL.TestStatement import com.google.common.base.Predicate import com.google.inject.Inject -import java.util.List import java.util.Map import java.util.Set import org.eclipse.emf.ecore.EObject @@ -53,9 +55,6 @@ import org.eclipse.xtext.scoping.IScope import org.eclipse.xtext.scoping.impl.AbstractGlobalScopeDelegatingScopeProvider import org.eclipse.xtext.scoping.impl.MapBasedScope import org.eclipse.xtext.util.OnChangeEvictingCache -import com.ge.research.sadl.sADL.SadlInstance -import com.ge.research.sadl.sADL.QueryStatement -import com.ge.research.sadl.sADL.TestStatement /** * This class contains custom scoping description. @@ -79,7 +78,8 @@ class SADLScopeProvider extends AbstractGlobalScopeDelegatingScopeProvider { return super.getGlobalScope(context.eResource, reference) } if (SADLPackage.Literals.SADL_RESOURCE.isSuperTypeOf(reference.EReferenceType)) { - return getSadlResourceScope(context, reference) + val result = getSadlResourceScope(context, reference) + return result } throw new UnsupportedOperationException( "Couldn't build scope for elements of type " + reference.EReferenceType.name) @@ -181,8 +181,11 @@ class SADLScopeProvider extends AbstractGlobalScopeDelegatingScopeProvider { return MapBasedScope.createScope(parent, map.values) } + @Data static class LocalSymbols { + } + protected def IScope createResourceScope(Resource resource, String alias, Set importedResources) { - return cache.get('resource_scope'->alias, resource) [ + return cache.get('resource_scope' -> alias, resource) [ val shouldWrap = importedResources.empty if (!importedResources.add(resource)) { return IScope.NULLSCOPE @@ -288,116 +291,68 @@ class SADLScopeProvider extends AbstractGlobalScopeDelegatingScopeProvider { protected def IScope createImportScope(Resource resource, Set importedResources) { val imports = resource.contents.head.eContents.filter(SadlImport).toList.reverseView - var importScopes = newArrayList + val importedSymbols = newHashMap for (imp : imports) { val externalResource = imp.importedResource - if (!externalResource.eIsProxy) - importScopes += createResourceScope(externalResource.eResource, imp.alias, importedResources) + if (!externalResource.eIsProxy) { + createResourceScope(externalResource.eResource, imp.alias, importedResources).allElements.forEach[ + val existing = importedSymbols.put(name, it) + val duplicateProblem = checkDuplicate(existing, it) + if (duplicateProblem !== null) { + importedSymbols.put(duplicateProblem.name, duplicateProblem) + } + ] + } + } - if (importScopes.isEmpty) { + if (importedSymbols.isEmpty) { if (!resource.URI.toString.endsWith("SadlImplicitModel.sadl")) { val element = getGlobalScope(resource, SADLPackage.Literals.SADL_IMPORT__IMPORTED_RESOURCE).getSingleElement(QualifiedName.create("http://sadl.org/sadlimplicitmodel")) if (element !== null) { val eobject = resource.resourceSet.getEObject(element.EObjectURI, true) if (eobject !== null) { - importScopes += createResourceScope(eobject.eResource, null, importedResources) + createResourceScope(eobject.eResource, null, importedResources).allElements.forEach[ + importedSymbols.put(name, it) + ] } } } } - return new ListCompositeScope(importScopes, converter, ambiguousNameDetection) + return new MapScope(IScope.NULLSCOPE, importedSymbols, false) } - - private def void addElement(Map scope, QualifiedName qn, EObject obj) { - if (!scope.containsKey(qn)) { - scope.put(qn, new EObjectDescription(qn, obj, emptyMap)) - } - } - - @Data static class ListCompositeScope implements IScope { - List delegates - IQualifiedNameConverter converter - boolean detectAmbiguousNames; - - override getAllElements() { - delegates.map[allElements].reduce[p1, p2| p1 + p2] ?: #[] - } - - override getElements(QualifiedName name) { - val registered = newHashSet - return delegates.map[getElements(name)].flatten.filter[registered.add(it.EObjectURI)] - } - - override getElements(EObject object) { - return delegates.map[getElements(object)].flatten + def private IEObjectDescription checkDuplicate(IEObjectDescription first, IEObjectDescription second) { + if (!ambiguousNameDetection || first === null || second === null || first.EObjectURI == second.EObjectURI) { + return null } + val imports = #[first, second].map[EObjectOrProxy.eResource.allContents.filter(SadlModel).head.baseUri] + val message = '''Ambiguously imported name '«first.name»' from «imports.map["'"+it+"'"].join(", ")». Please use an alias or choose different names.''' - override getSingleElement(QualifiedName name) { - if (!detectAmbiguousNames) { - for (s : delegates) { - val element = s.getSingleElement(name); - if (element !== null) { - return element - } + return new ForwardingEObjectDescription(first) { + override getUserData(String key) { + if (key.equals(ErrorAddingLinkingService.ERROR)) { + return message } - return null; - } - var List candidates = null - var IEObjectDescription firstMatch = null - for (s : delegates) { - val candidate = s.getSingleElement(name) - if (candidate !== null && firstMatch !== candidate) { - if (firstMatch === null) { - firstMatch = candidate - } else { - if (candidates === null) { - candidates = newArrayList - candidates.add(firstMatch) - } - if (!candidates.contains(candidate)) - candidates.add(candidate) - } - } - } - if (candidates === null) { - return firstMatch - } else { - val imports = candidates.map[EObjectOrProxy.eResource.allContents.filter(SadlModel).head.baseUri] - val message = '''Ambiguously imported name '«name»' from «imports.map["'"+it+"'"].join(", ")». Please use an alias or choose different names.''' - val alternatives = candidates.map[ - desc | - this.getElements(desc.EObjectOrProxy) - .filter - [ - qualifiedName != desc.qualifiedName - ] - ].flatten.toList - - return new ForwardingEObjectDescription(candidates.head) { - override getUserData(String key) { - if (key.equals(ErrorAddingLinkingService.ERROR)) { - return message - } - if (key.equals(ErrorAddingLinkingService.ALTERNATIVES)) { - return alternatives.join(",", [converter.toString(name)]) - } - super.getUserData(key) - } + if (key.equals(ErrorAddingLinkingService.ALTERNATIVES)) { + return first.qualifiedName+","+second.qualifiedName } + super.getUserData(key) } } - - override getSingleElement(EObject object) { - for (scope : delegates) { - val element = scope.getSingleElement(object) - if (element !== null) { - return element - } - } - return null + } + + static class MapScope extends MapBasedScope { + + new(IScope parent, Map elements, boolean ignoreCase) { + super(parent, elements, ignoreCase) } } + private def void addElement(Map scope, QualifiedName qn, EObject obj) { + if (!scope.containsKey(qn)) { + scope.put(qn, new EObjectDescription(qn, obj, emptyMap)) + } + } + }