aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhbehrens2008-11-14 05:09:05 (EST)
committersefftinge2008-11-14 05:09:05 (EST)
commit4326848e260fb4d9e76a7fb98d7f5fac070b4120 (patch)
treefdb3b522567b095f5dd4e1e0c9fe9cb3698c4940
parent5009cac601501ce92f324a62703910b4a36db221 (diff)
downloadorg.eclipse.xtext-4326848e260fb4d9e76a7fb98d7f5fac070b4120.zip
org.eclipse.xtext-4326848e260fb4d9e76a7fb98d7f5fac070b4120.tar.gz
org.eclipse.xtext-4326848e260fb4d9e76a7fb98d7f5fac070b4120.tar.bz2
Redesign of linking phase with respect to performance (Huge patch from Sebastian), Refers to Bug 255037, Bug 254995 and Bug 254859
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java123
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java26
-rw-r--r--tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/crossrefs/CrossRefTest.java62
-rw-r--r--tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/generator/AutoTestSuite.java1
-rw-r--r--tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourcePerformanceTest.java61
-rw-r--r--tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourceTest.java113
-rw-r--r--tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/metamodel/ResourceTests.java4
-rw-r--r--tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/util/SimpleCacheTest.java71
8 files changed, 345 insertions, 116 deletions
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java
index 609579e..3beacaf 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java
@@ -8,7 +8,6 @@ import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
-import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -22,6 +21,7 @@ import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.LexerRule;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.RuleCall;
+import org.eclipse.xtext.crossref.ILinkingNameService;
import org.eclipse.xtext.crossref.ILinkingService;
import org.eclipse.xtext.parsetree.AbstractNode;
import org.eclipse.xtext.parsetree.CompositeNode;
@@ -29,7 +29,7 @@ import org.eclipse.xtext.parsetree.LeafNode;
import org.eclipse.xtext.parsetree.NodeUtil;
import org.eclipse.xtext.parsetree.ParseTreeUtil;
import org.eclipse.xtext.service.Inject;
-import org.eclipse.xtext.util.Pair;
+import org.eclipse.xtext.util.Strings;
/**
* Convenient super class for <code>IProposalProvider</code> implementations.
@@ -50,9 +50,15 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
@Inject
protected ILinkingService linkingService;
+ @Inject
+ protected ILinkingNameService linkingNameService;
+
/*
* (non-Javadoc)
- * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#completeKeyword(org.eclipse.xtext.Keyword, org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int)
+ *
+ * @see
+ * org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#completeKeyword(org.eclipse.xtext.Keyword,
+ * org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int)
*/
public List<? extends ICompletionProposal> completeKeyword(Keyword keyword, EObject model, String prefix,
IDocument doc, int offset) {
@@ -66,7 +72,10 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
/*
* (non-Javadoc)
- * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#completeRuleCall(org.eclipse.xtext.RuleCall, org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int)
+ *
+ * @see
+ * org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#completeRuleCall(org.eclipse.xtext.RuleCall,
+ * org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int)
*/
public List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, EObject model, String prefix,
IDocument doc, int offset) {
@@ -84,10 +93,12 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
return Collections.emptyList();
}
-
/*
* (non-Javadoc)
- * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#sortAndFilter(java.util.List, org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int, org.eclipse.xtext.parsetree.AbstractNode, org.eclipse.xtext.parsetree.LeafNode)
+ *
+ * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#sortAndFilter(java.util.List,
+ * org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int,
+ * org.eclipse.xtext.parsetree.AbstractNode, org.eclipse.xtext.parsetree.LeafNode)
*/
public List<? extends ICompletionProposal> sortAndFilter(
List<? extends ICompletionProposal> completionProposalList, EObject model, String prefix,
@@ -96,25 +107,21 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
}
/**
- * Concrete subclasses can override this to provide a more meaningful and
- * sophisticated behaviour whenever a list of ICompletionProposal's should
- * be computed for simple <code>LexerRule</code> call's.
+ * Concrete subclasses can override this to provide a more meaningful and sophisticated behaviour whenever a list of
+ * ICompletionProposal's should be computed for simple <code>LexerRule</code> call's.
*
- * This implementation returns one <code>ICompletionProposal</code> with a
- * displayString composed of the name of the containing rule plus the
- * featurename of an optional assignment and at the end the name of the
- * given LexerRule (e.i. ParserRuleName+AssignmentFeatureName+LexerRuleName)
- * or {@link #getDefaultIntegerValue()} if its <i>INT</i> based LexerRule.
+ * This implementation returns one <code>ICompletionProposal</code> with a displayString composed of the name of the
+ * containing rule plus the featurename of an optional assignment and at the end the name of the given LexerRule
+ * (e.i. ParserRuleName+AssignmentFeatureName+LexerRuleName) or {@link #getDefaultIntegerValue()} if its <i>INT</i>
+ * based LexerRule.
*
* @param lexerRule
* the 'called' LexerRule instance
* @param ruleCall
* the ruleCall for the provided lexerRule
* @param offset
- * an offset within the document for which completions should be
- * computed
- * @return a computed list of <code>ICompletionProposal</code> for the given
- * <code>LexerRule</code>
+ * an offset within the document for which completions should be computed
+ * @return a computed list of <code>ICompletionProposal</code> for the given <code>LexerRule</code>
*/
protected List<? extends ICompletionProposal> doCompleteLexerRuleRuleCall(LexerRule lexerRule, RuleCall ruleCall,
EObject model, int offset) {
@@ -145,30 +152,26 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
/**
*
- * @return the id of the plug-in containing the image files; <code>null
- * </code> is returned if the plug-in does not exist
+ * @return the id of the plug-in containing the image files; <code>null </code> is returned if the plug-in does not
+ * exist
*/
protected abstract String getPluginId();
/**
- * Returns the the relative path of the default image file, relative to the
- * root of the containing plug-in; the path must be legal The image would
- * typically be shown to the left of the <code>ICompletionProposal</code>
- * display string.
+ * Returns the the relative path of the default image file, relative to the root of the containing plug-in; the path
+ * must be legal The image would typically be shown to the left of the <code>ICompletionProposal</code> display
+ * string.
*
- * @return the image file path of the default image to be shown or
- * <code>null</code> if no image is desired
+ * @return the image file path of the default image to be shown or <code>null</code> if no image is desired
* @see #getPluginId()
*/
protected abstract String getDefaultImageFilePath();
/**
- * Concrete subclasses can override this to provide custom lookup behaviour
- * for <code>CrossReference</code>. This implementation delegates to the
- * injected LinkingService
+ * Concrete subclasses can override this to provide custom lookup behaviour for <code>CrossReference</code>. This
+ * implementation delegates to the injected LinkingService
*
- * @return a list of <code>ICompletionProposal</code> matching the given
- * assignment
+ * @return a list of <code>ICompletionProposal</code> matching the given assignment
*/
protected List<? extends ICompletionProposal> lookupCrossReference(CrossReference crossReference, EObject model,
String prefix, int offset) {
@@ -176,11 +179,10 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>();
if (linkingService != null) {
- List<Pair<String, URI>> candidates = linkingService
- .getLinkCandidates(model, crossReference, prefix);
- for (Pair<String, URI> candidate : candidates) {
- completionProposalList.add(createCompletionProposal(crossReference, model, candidate.getFirstElement(),
- offset));
+ List<EObject> candidates = linkingService.getLinkCandidates(model, crossReference, prefix);
+ for (EObject candidate : candidates) {
+ completionProposalList.add(createCompletionProposal(crossReference, model, linkingNameService.getText(
+ candidate, crossReference), offset));
}
}
@@ -188,46 +190,47 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
}
/**
- * @return a new <code>XtextCompletionProposal</code> for the given text and
- * offset.
+ * @return a new <code>XtextCompletionProposal</code> for the given text and offset.
*/
protected final XtextCompletionProposal createCompletionProposal(AbstractElement abstractElement, EObject model,
String text, int offset) {
return new XtextCompletionProposal(abstractElement, model, text, new StyledString(text), text,
getDefaultImageFilePath(), getPluginId(), offset);
}
-
+
/**
- * Concrete subclasses can override this for custom sort and filter
- * behavior. Gets called after all completion proposals have been collected.
+ * Concrete subclasses can override this for custom sort and filter behavior. Gets called after all completion
+ * proposals have been collected.
*
- * The default behavior of this implementation is to sort duplicates and to
- * trim matching <code>ICompletionProposal#displayString</code> with matching prefix values.
+ * The default behavior of this implementation is to sort duplicates and to trim matching
+ * <code>ICompletionProposal#displayString</code> with matching prefix values.
*
- * @see #sortAndFilter(List, EObject, String, IDocument, int, AbstractNode, LeafNode)
+ * @see #sortAndFilter(List, EObject, String, IDocument, int, AbstractNode, LeafNode)
*/
protected List<? extends ICompletionProposal> doSortAndFilter(
- List<? extends ICompletionProposal> completionProposalList, EObject model, String prefix,IDocument document, int offset) {
+ List<? extends ICompletionProposal> completionProposalList, EObject model, String prefix,
+ IDocument document, int offset) {
Map<String, ICompletionProposal> displayString2ICompletionProposalMap = new HashMap<String, ICompletionProposal>();
-
+
for (Iterator<? extends ICompletionProposal> iterator = completionProposalList.iterator(); iterator.hasNext();) {
ICompletionProposal completionProposal = iterator.next();
-
+
// filter duplicate displayString
if (!displayString2ICompletionProposalMap.containsKey(completionProposal.getDisplayString())) {
displayString2ICompletionProposalMap.put(completionProposal.getDisplayString(), completionProposal);
-
+
if (model != null) {
-
+
CompositeNode parserNode = NodeUtil.getRootNode(model);
-
- LeafNode currentLeafNode=ParseTreeUtil.getCurrentNodeByOffset(parserNode, offset);
- boolean isCursorAtTheEndOfTheLastElement = offset == (currentLeafNode.getOffset() + currentLeafNode.getLength());
-
+ LeafNode currentLeafNode = ParseTreeUtil.getCurrentNodeByOffset(parserNode, offset);
+
+ boolean isCursorAtTheEndOfTheLastElement = offset == (currentLeafNode.getOffset() + currentLeafNode
+ .getLength());
+
if (isCursorAtTheEndOfTheLastElement && completionProposal instanceof XtextCompletionProposal) {
XtextCompletionProposal xtextCompletionProposal = (XtextCompletionProposal) completionProposal;
@@ -236,16 +239,16 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
EObject grammarElement = currentLeafNode.getGrammarElement();
// at the end of the last element we want to filter only the CompletionProposal for the same grammar element
- if (((isCursorAtTheEndOfTheLastElement && abstractElement.equals(grammarElement))
- || !isCursorAtTheEndOfTheLastElement) && !completionProposal.getDisplayString().startsWith(currentLeafNode.getText())) {
+ if (((isCursorAtTheEndOfTheLastElement && abstractElement.equals(grammarElement)) || !isCursorAtTheEndOfTheLastElement)
+ && !completionProposal.getDisplayString().startsWith(currentLeafNode.getText())) {
if (logger.isDebugEnabled()) {
logger.debug("filter completionProposal '" + completionProposal + "'");
}
iterator.remove();
}
- }
+ }
}
-
+
}
else {
if (logger.isDebugEnabled()) {
@@ -255,7 +258,6 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
iterator.remove();
}
}
-
return completionProposalList;
}
@@ -266,10 +268,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider {
* @return the provided string with the first letter capitalized
*/
protected final String firstLetterCapitalized(String text) {
- if (text == null || text.length() == 0) {
- return text;
- }
- return text.substring(0, 1).toUpperCase() + text.substring(1, text.length());
+ return Strings.toFirstUpper(text);
}
}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java
index 6331160..84223db 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java
@@ -8,7 +8,6 @@ import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
@@ -49,18 +48,18 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
@Inject
private IProposalProvider proposalProvider;
-
/**
- * @param proposalProvider the proposalProvider to set
+ * @param proposalProvider
+ * the proposalProvider to set
*/
public void setProposalProvider(IProposalProvider proposalProvider) {
this.proposalProvider = proposalProvider;
}
/**
- * computes the possible grammar elements following the one at the given
- * offset and calls the respective methods on the proposal provider.
+ * computes the possible grammar elements following the one at the given offset and calls the respective methods on
+ * the proposal provider.
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, final int offset) {
@@ -97,8 +96,8 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
Set<AbstractElement> nextValidElementSet = new LinkedHashSet<AbstractElement>();
/**
- * in case of a crossreference which isnt linked already we
- * evaluate it again and delegate to proposalProvider (again)
+ * in case of a crossreference which isnt linked already we evaluate it again and delegate to
+ * proposalProvider (again)
*/
if (lastCompleteNode.getGrammarElement() instanceof CrossReference && !isLinked(lastCompleteNode)) {
nextValidElementSet.add((AbstractElement) lastCompleteNode.getGrammarElement());
@@ -106,9 +105,8 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
offset));
}
/**
- * in case of 'at-the-end' of the previous,completed element we
- * evaluate it again for 'right-to-left-backtracking' cases
- * (e.g. for keyword 'kind' kind>|< |=cursorpos)
+ * in case of 'at-the-end' of the previous,completed element we evaluate it again for
+ * 'right-to-left-backtracking' cases (e.g. for keyword 'kind' kind>|< |=cursorpos)
*/
else if (currentLeafNode == lastCompleteNode) {
nextValidElementSet = ParseTreeUtil
@@ -195,19 +193,17 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
EReference eReference = getReference(crossReference, semanticModel.eClass());
List<EObject> referencedObjects = EcoreUtil2.getAllReferencedObjects(semanticModel, eReference);
-
+
if (referencedObjects.isEmpty())
return false;
else {
- List<URI> referencedURIs = EcoreUtil2.getURIs(referencedObjects);
- List<URI> linkCandidates = linkingService.getLinkedObjects(semanticModel, crossReference,
+ List<EObject> linkCandidates = linkingService.getLinkedObjects(semanticModel, crossReference,
(LeafNode) lastCompleteNode);
- return !linkCandidates.isEmpty() && referencedURIs.containsAll(linkCandidates);
+ return !linkCandidates.isEmpty() && referencedObjects.containsAll(linkCandidates);
}
}
private EReference getReference(CrossReference ref, EClass class1) {
-
EList<EReference> references = class1.getEAllReferences();
String feature = GrammarUtil.containingAssignment(ref).getFeature();
diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/crossrefs/CrossRefTest.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/crossrefs/CrossRefTest.java
index e4fa850..8990216 100644
--- a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/crossrefs/CrossRefTest.java
+++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/crossrefs/CrossRefTest.java
@@ -3,77 +3,67 @@ package org.eclipse.xtext.crossrefs;
import java.util.List;
import org.apache.log4j.Logger;
-import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xtext.Assignment;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.Group;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.crossref.ILinkingService;
+import org.eclipse.xtext.crossref.impl.XtextBuiltinLinkingService;
import org.eclipse.xtext.crossrefs.services.LangAGrammarAccess;
import org.eclipse.xtext.service.ServiceRegistry;
import org.eclipse.xtext.tests.AbstractGeneratorTest;
-import org.eclipse.xtext.util.Pair;
public class CrossRefTest extends AbstractGeneratorTest {
private static final Logger logger = Logger.getLogger(CrossRefTest.class);
- private ILinkingService linkingService;
-
+ private XtextBuiltinLinkingService linkingService;
+
@Override
protected void setUp() throws Exception {
super.setUp();
with(LangAStandaloneSetup.class);
- linkingService = ServiceRegistry.getService(ILangA.SCOPE, ILinkingService.class);
+ linkingService = (XtextBuiltinLinkingService) ServiceRegistry.getService(ILangA.SCOPE, ILinkingService.class);
}
-
+
public void testSimple() throws Exception {
EObject model = getModel("type A extends B type B extends A");
logger.debug(invokeWithXtend("types.collect(e|e.name+' '+e.extends.name).toString(',')", model));
assertWithXtend("'B'", "types.first().extends.name", model);
assertWithXtend("types.first()", "types.first().extends.extends", model);
}
-
- public void testGetLinkText() throws Exception {
- EObject model = getModel("type A extends B type B extends A");
- EObject typeA = model.eResource().getEObject("A");
- EObject typeB = model.eResource().getEObject("B");
- URI uriA = EcoreUtil.getURI(typeA);
- URI uriB = EcoreUtil.getURI(typeB);
- assertEquals("A", linkingService.getLinkAsText(typeA, uriA));
- assertEquals("B", linkingService.getLinkAsText(typeA, uriB));
- assertEquals("A", linkingService.getLinkAsText(typeB, uriA));
- assertEquals("B", linkingService.getLinkAsText(typeB, uriB));
- }
-
+
public void testGetLinkCandidates01() throws Exception {
EObject model = getModel("type TypeA extends TypeB type TypeB extends TypeA type AnotherType extends TypeA");
-
+
assertWithXtend("3", "types.size", model);
-
+
EObject context = (EObject) invokeWithXtend("types.first()", model);
ParserRule prType = new LangAGrammarAccess().pr_Type();
- Assignment asExtends = (Assignment)((Group)prType.getAlternatives()).getAbstractTokens().get(1);
+ Assignment asExtends = (Assignment) ((Group) prType.getAlternatives()).getAbstractTokens().get(1);
CrossReference xref = (CrossReference) asExtends.getTerminal();
-
- assertEquals(3, linkingService.getLinkCandidates(context, xref, "").size());
- assertEquals(2, linkingService.getLinkCandidates(context, xref, "Type").size());
- assertEquals(1, linkingService.getLinkCandidates(context, xref, "TypeA").size());
- assertEquals(0, linkingService.getLinkCandidates(context, xref, "TypeC").size());
+
+ assertEquals(3, linkingService.doGetLinkedObjects(context, xref, "", false).size());
+ assertEquals(2, linkingService.doGetLinkedObjects(context, xref, "Type", false).size());
+ assertEquals(1, linkingService.doGetLinkedObjects(context, xref, "TypeA", false).size());
+ assertEquals(0, linkingService.doGetLinkedObjects(context, xref, "TypeC", false).size());
}
-
+
public void testGetLinkCandidates02() throws Exception {
EObject model = getModel("type TypeA extends TypeB type TypeB extends TypeA type AnotherType extends TypeA");
-
+
EObject context = (EObject) invokeWithXtend("types.first()", model);
ParserRule prType = new LangAGrammarAccess().pr_Type();
- Assignment asExtends = (Assignment)((Group)prType.getAlternatives()).getAbstractTokens().get(1);
+ Assignment asExtends = (Assignment) ((Group) prType.getAlternatives()).getAbstractTokens().get(1);
CrossReference xref = (CrossReference) asExtends.getTerminal();
-
- List<Pair<String, URI>> candidates = linkingService.getLinkCandidates(context, xref, "TypeA");
+
+ List<EObject> candidates = linkingService.getLinkCandidates(context, xref, "TypeA");
assertEquals(1, candidates.size());
- Pair<String, URI> candidate = candidates.get(0);
- assertEquals("TypeA", candidate.getFirstElement());
- assertEquals(model.eResource().getURI().appendFragment("TypeA"), candidate.getSecondElement());
+ EObject candidate = candidates.get(0);
+ EStructuralFeature feature = candidate.eClass().getEStructuralFeature("name");
+ assertNotNull(feature);
+ Object name = candidate.eGet(feature);
+ assertNotNull(name);
+ assertEquals("TypeA", name);
}
}
diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/generator/AutoTestSuite.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/generator/AutoTestSuite.java
index 72d0993..1227d21 100644
--- a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/generator/AutoTestSuite.java
+++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/generator/AutoTestSuite.java
@@ -46,6 +46,7 @@ public class AutoTestSuite {
suite.addTestSuite(org.eclipse.xtext.resource.metamodel.TypeHierarchyHelperTests.class);
suite.addTestSuite(org.eclipse.xtext.crossrefs.CrossRefTest.class);
suite.addTestSuite(org.eclipse.xtext.crossrefs.LinkingErrorTest.class);
+ suite.addTestSuite(org.eclipse.xtext.util.SimpleCacheTest.class);
return suite;
}
}
diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourcePerformanceTest.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourcePerformanceTest.java
new file mode 100644
index 0000000..d6758b1
--- /dev/null
+++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourcePerformanceTest.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
+ * 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
+ *******************************************************************************/
+package org.eclipse.xtext.resource;
+
+import org.eclipse.xtext.testlanguages.ReferenceGrammarStandaloneSetup;
+import org.eclipse.xtext.tests.AbstractGeneratorTest;
+
+/**
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+public class XtextResourcePerformanceTest extends AbstractGeneratorTest {
+
+ private static final int NUM_ELEMENTS = 100;
+ private String model;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ with(ReferenceGrammarStandaloneSetup.class);
+ StringBuilder modelBuilder = new StringBuilder(NUM_ELEMENTS * 64);
+ modelBuilder.append("spielplatz " + NUM_ELEMENTS + " {\r\n");
+ for(int i = 1; i <= NUM_ELEMENTS; i++ ) {
+ modelBuilder.append(" kind (Bob" + i + " " + i + ")\r\n");
+ modelBuilder.append(" kind (Joe" + i + " " + i + ")\r\n");
+ modelBuilder.append(" erwachsener (Mutter" + i + " " + i + ")\r\n");
+ modelBuilder.append(" erwachsener (Vater" + i + " " + i + ")\r\n");
+ modelBuilder.append(" familie(Familie" + i + " Vater" + i + " Mutter" + i + " Bob" + i + ", Joe" + i + ")\r\n");
+ }
+ modelBuilder.append('}');
+ model = modelBuilder.toString();
+ }
+
+ public void testLoad() throws Exception {
+ XtextResource resource = getResourceFromString(model);
+ assertNotNull(resource);
+ assertTrue(resource.getParseResult().getParseErrors().isEmpty());
+ }
+
+ public void testLoadModelWithLinkingErrors() throws Exception {
+ StringBuilder modelBuilder = new StringBuilder(NUM_ELEMENTS * 64);
+ modelBuilder.append("spielplatz " + NUM_ELEMENTS + " {\r\n");
+ for(int i = 1; i <= NUM_ELEMENTS; i++ ) {
+ modelBuilder.append(" kind (Bob " + i + ")\r\n");
+ modelBuilder.append(" kind (Joe " + i + ")\r\n");
+ modelBuilder.append(" erwachsener (Mutter " + i + ")\r\n");
+ modelBuilder.append(" erwachsener (Vater " + i + ")\r\n");
+ modelBuilder.append(" familie(Familie" + i + " Vater Mutter Bob, Joe)\r\n");
+ }
+ modelBuilder.append('}');
+ model = modelBuilder.toString();
+ XtextResource resource = getResourceFromString(model);
+ assertNotNull(resource);
+ assertTrue(resource.getParseResult().getParseErrors().isEmpty());
+ assertEquals(2 * NUM_ELEMENTS, resource.getErrors().size());
+ }
+
+}
diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourceTest.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourceTest.java
new file mode 100644
index 0000000..1e8a46b
--- /dev/null
+++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/XtextResourceTest.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
+ * 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
+ *******************************************************************************/
+package org.eclipse.xtext.resource;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.xtext.parser.IParseResult;
+import org.eclipse.xtext.testlanguages.ReferenceGrammarStandaloneSetup;
+import org.eclipse.xtext.tests.AbstractGeneratorTest;
+
+/**
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+public class XtextResourceTest extends AbstractGeneratorTest {
+
+ private XtextResource resource;
+ private String simpleModel = "spielplatz 1 { kind ( Bob 0 ) }";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ with(ReferenceGrammarStandaloneSetup.class);
+ resource = getResourceFromString("");
+ }
+
+ public void testInitialState() throws Exception {
+ assertNotNull(resource);
+ assertTrue(resource.isLoaded());
+ assertFalse("resource.isTrackingModification()", resource.isTrackingModification());
+ assertFalse(resource.isModified());
+ assertTrue(resource.getErrors().isEmpty());
+ assertTrue(resource.getWarnings().isEmpty());
+
+ IParseResult parseResult = resource.getParseResult();
+ assertNotNull("parseResult", parseResult);
+ assertNotNull(parseResult.getRootNode());
+ assertEquals(0, parseResult.getParseErrors().size());
+ assertEquals(0, parseResult.getRootNode().getLength());
+ assertNull(parseResult.getRootASTElement());
+ }
+
+ public void testModify_01() throws Exception {
+ resource.update(0, 0, simpleModel);
+ assertFalse(resource.isModified());
+ }
+
+ public void testModify_02() throws Exception {
+ resource.reparse(simpleModel);
+ assertFalse(resource.isModified());
+ }
+
+ public void testModify_03() throws Exception {
+ resource.reparse(simpleModel);
+ assertFalse(resource.isModified());
+ modifySpielplatz();
+ assertFalse(resource.isModified());
+ }
+
+ public void testModify_04() throws Exception {
+ resource.setTrackingModification(true);
+ resource.update(0, 0, simpleModel);
+ assertFalse(resource.isModified());
+ }
+
+ public void testModify_05() throws Exception {
+ resource.setTrackingModification(true);
+ resource.reparse(simpleModel);
+ assertFalse(resource.isModified());
+ }
+
+ public void testModify_06() throws Exception {
+ resource.setTrackingModification(true);
+ resource.reparse(simpleModel);
+ assertFalse(resource.isModified());
+ modifySpielplatz();
+ assertTrue(resource.isModified());
+ }
+
+ private void modifySpielplatz() {
+ EObject obj = resource.getParseResult().getRootASTElement();
+ assertNotNull(obj);
+ assertEquals("Spielplatz", obj.eClass().getName());
+ EStructuralFeature feature = obj.eClass().getEStructuralFeature("groesse");
+ assertNotNull(feature);
+ assertEquals(1, obj.eGet(feature));
+ obj.eSet(feature, 3);
+ }
+
+ public void testUnload() throws Exception {
+ resource.reparse(simpleModel);
+ IParseResult parseResult = resource.getParseResult();
+ resource.unload();
+ assertNull(resource.getParseResult());
+ assertTrue(parseResult.getRootASTElement().eIsProxy());
+ }
+
+ public void testUpdate() throws Exception {
+ resource.update(0, 0, simpleModel);
+
+ IParseResult parseResult = resource.getParseResult();
+ assertNotNull("parseResult", parseResult);
+ assertNotNull(parseResult.getRootNode());
+ assertEquals(0, parseResult.getParseErrors().size());
+ assertEquals(simpleModel.length(), parseResult.getRootNode().getLength());
+ assertNotNull(parseResult.getRootASTElement());
+ }
+
+
+}
diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/metamodel/ResourceTests.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/metamodel/ResourceTests.java
index f6a694d..a89ad76 100644
--- a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/metamodel/ResourceTests.java
+++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/resource/metamodel/ResourceTests.java
@@ -24,10 +24,8 @@ public class ResourceTests extends AbstractGeneratorTest {
public void testFragmentsWorkInBothDirections() throws Exception {
EObject model = getModel("type A extends B type B extends A");
EObject typeA1 = (EObject) invokeWithXtend("types.first()", model);
- EObject typeA2 = model.eResource().getEObject("A");
+ EObject typeA2 = model.eResource().getEObject(model.eResource().getURIFragment(typeA1));
assertEquals(typeA1, typeA2);
- String uriFrament = model.eResource().getURIFragment(typeA1);
- assertEquals("A", uriFrament);
}
}
diff --git a/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/util/SimpleCacheTest.java b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/util/SimpleCacheTest.java
new file mode 100644
index 0000000..bbaa495
--- /dev/null
+++ b/tests/org.eclipse.xtext.generator.tests/src/org/eclipse/xtext/util/SimpleCacheTest.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
+ * 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
+ *******************************************************************************/
+package org.eclipse.xtext.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+public class SimpleCacheTest extends TestCase implements Function<String, String>{
+
+ private SimpleCache<String, String> cache;
+
+ private String expectedParam;
+
+ private int callCount;
+
+ protected void setUp() throws Exception {
+ this.cache = new SimpleCache<String, String>(this);
+ expectedParam = null;
+ callCount = 0;
+ }
+
+ public String exec(String param) {
+ assertEquals(expectedParam, param);
+ callCount++;
+ return param + param;
+ }
+
+ public void testInitial() {
+ assertEquals(0, cache.getSize());
+ }
+
+ public void testGet() {
+ expectedParam = new String("param"); // is not interned
+ String cached = cache.get(expectedParam);
+ assertEquals("paramparam", cached);
+ assertEquals(1, callCount);
+ assertEquals(1, cache.getSize());
+ assertSame(cached, cache.get(new String(expectedParam)));
+ assertEquals(1, callCount);
+ assertEquals(1, cache.getSize());
+ }
+
+ public void testDiscard() {
+ String first = new String("first"); // is not interned
+ expectedParam = first;
+ cache.get(expectedParam);
+ String second = new String("second"); // is not interned
+ expectedParam = second;
+ cache.get(expectedParam);
+ assertEquals(2, cache.getSize());
+ cache.discard(expectedParam);
+ assertEquals(1, cache.getSize());
+ assertFalse(cache.hasCachedValue(expectedParam));
+ }
+
+ public void testClear() {
+ expectedParam = new String("param"); // is not interned
+ cache.get(expectedParam);
+ assertEquals(1, cache.getSize());
+ cache.clear();
+ assertEquals(0, cache.getSize());
+ }
+
+}