package com.google.dart.engine.services.completion; import com.google.common.base.Joiner; import com.google.dart.engine.ast.CompilationUnit; import com.google.dart.engine.context.AnalysisContext; import com.google.dart.engine.context.AnalysisException; import com.google.dart.engine.element.CompilationUnitElement; import com.google.dart.engine.element.Element; import com.google.dart.engine.element.LibraryElement; import com.google.dart.engine.index.Index; import com.google.dart.engine.index.IndexFactory; import com.google.dart.engine.index.Location; import com.google.dart.engine.index.Relationship; import com.google.dart.engine.index.RelationshipCallback; import com.google.dart.engine.internal.index.IndexConstants; import com.google.dart.engine.internal.index.file.MemoryNodeManager; import com.google.dart.engine.resolver.ResolverTestCase; import com.google.dart.engine.search.SearchEngine; import com.google.dart.engine.search.SearchEngineFactory; import com.google.dart.engine.services.assist.AssistContext; import com.google.dart.engine.services.util.LocationSpec; import com.google.dart.engine.services.util.MockCompletionRequestor; import com.google.dart.engine.source.Source; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class CompletionTestCase extends ResolverTestCase { /** * Replaces "!" with the {@link CompletionProposal#CURSOR_MARKER}. */ protected static String resultWithCursor(String result) { return result.replace('!', CompletionProposal.CURSOR_MARKER); } protected static String src(String... parts) { return Joiner.on('\n').join(parts); } protected Index index; protected SearchEngine searchEngine; @Override public void setUp() { super.setUp(); index = IndexFactory.newIndex(IndexFactory.newSplitIndexStore(new MemoryNodeManager())); new Thread() { @Override public void run() { index.run(); index = null; } }.start(); searchEngine = SearchEngineFactory.createSearchEngine(index); } /** * Resolve and index all of the compilation units that comprise the libraries specified by the * given sources, returning the resolved compilation unit for the last library in the list. * * @param sources the sources of the libraries to be resolved and indexed * @throws AnalysisException if the libraries could not be resolved or indexed */ protected CompilationUnit resolveAndIndex(List<Source> sources) throws AnalysisException { AnalysisContext context = getAnalysisContext(); CompilationUnit libraryUnit = null; for (Source source : sources) { LibraryElement library = resolve(source); libraryUnit = getAnalysisContext().resolveCompilationUnit(source, library); index.indexUnit(context, libraryUnit); for (CompilationUnitElement partElement : library.getParts()) { CompilationUnit partUnit = getAnalysisContext().resolveCompilationUnit( partElement.getSource(), library); index.indexUnit(context, partUnit); } } return libraryUnit; } @Override protected void tearDown() throws Exception { index.getRelationships( IndexConstants.UNIVERSE, IndexConstants.IS_READ_BY, new RelationshipCallback() { @Override public void hasRelationships(Element a, Relationship b, Location[] c) { index.stop(); } }); searchEngine = null; super.tearDown(); } /** * Run a set of completion tests on the given <code>originalSource</code>. The source string has * completion points embedded in it, which are identified by '!X' where X is a single character. * Each X is matched to positive or negative results in the array of * <code>validationStrings</code>. Validation strings contain the name of a prediction with a two * character prefix. The first character of the prefix corresponds to an X in the * <code>originalSource</code>. The second character is either a '+' or a '-' indicating whether * the string is a positive or negative result. * * @param originalSource The source for a completion test that contains completion points * @param validationStrings The positive and negative predictions */ protected void test(String originalSource, List<Source> sources, String... results) throws URISyntaxException, AnalysisException { Collection<LocationSpec> completionTests = LocationSpec.from(originalSource, results); assertTrue( "Expected exclamation point ('!') within the source" + " denoting the position at which code completion should occur", !completionTests.isEmpty()); Source source = addSource(completionTests.iterator().next().source); sources.add(source); CompilationUnit compilationUnit = resolveAndIndex(sources); AnalysisContext analysisContext = getAnalysisContext(); CompletionFactory factory = new CompletionFactory(); for (LocationSpec test : completionTests) { MockCompletionRequestor requestor = new MockCompletionRequestor(); CompletionEngine engine = new CompletionEngine(requestor, factory); engine.complete(new AssistContext( searchEngine, analysisContext, null, source, compilationUnit, test.testLocation, 0)); if (test.positiveResults.size() > 0) { assertTrue( "Test " + test.id + " expected code completion suggestions " + String.valueOf(test.positiveResults), requestor.validate()); } for (String result : test.positiveResults) { requestor.assertSuggested(result, test.id); } for (String result : test.negativeResults) { requestor.assertNotSuggested(result, test.id); } TestAll.Count += test.positiveResults.size() + test.negativeResults.size(); } } /** * Run a set of completion tests on the given <code>originalSource</code>. The source string has * completion points embedded in it, which are identified by '!X' where X is a single character. * Each X is matched to positive or negative results in the array of * <code>validationStrings</code>. Validation strings contain the name of a prediction with a two * character prefix. The first character of the prefix corresponds to an X in the * <code>originalSource</code>. The second character is either a '+' or a '-' indicating whether * the string is a positive or negative result. * * @param originalSource The source for a completion test that contains completion points * @param validationStrings The positive and negative predictions */ protected void test(String originalSource, String... results) throws URISyntaxException, AnalysisException { test(originalSource, new ArrayList<Source>(), results); } }