@Override public List<CompletionItem> apply(CamelCatalog catalog) { Stream<EndpointOptionModel> endpointOptions = ModelHelper.generateComponentModel(catalog.componentJSonSchema(camelComponentName), true).getEndpointOptions().stream(); return endpointOptions .filter(endpoint -> "parameter".equals(endpoint.getKind())) .filter(endpoint -> { String group = endpoint.getGroup(); if (isProducer) { return !"consumer".equals(group); } else { return !"producer".equals(group); } }) .map(parameter -> { CompletionItem completionItem = new CompletionItem(parameter.getName()); String insertText = parameter.getName() + "="; if(parameter.getDefaultValue() != null) { insertText += parameter.getDefaultValue(); } completionItem.setInsertText(insertText); return completionItem; }) .collect(Collectors.toList()); }
public CompletableFuture<List<CompletionItem>> getCompletions(Position position) { if(textDocumentItem != null) { try { Node correspondingCamelNode = parserFileHelper.getCorrespondingCamelNodeForCompletion(textDocumentItem, position.getLine()); if (correspondingCamelNode != null) { String line = parserFileHelper.getLine(textDocumentItem, position); String camelComponentUri = parserFileHelper.getCamelComponentUri(textDocumentItem, position); CamelURIInstance camelURIInstance = new CamelURIInstance(camelComponentUri, correspondingCamelNode); int positionInCamelUri = position.getCharacter() - line.indexOf("uri=") - 5; CamelUriElementInstance camelUriElementInstance = camelURIInstance.getSpecificElement(positionInCamelUri); return camelUriElementInstance.getCompletions(camelCatalog, positionInCamelUri); } } catch (Exception e) { LOGGER.error("Error searching for corresponding node elements", e); } } return CompletableFuture.completedFuture(Collections.emptyList()); }
@Test public void testChangeEventUpdatesStoredText() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer("<to uri=\"\" xmlns=\"http://camel.apache.org/schema/blueprint\"></to>\n"); DidChangeTextDocumentParams changeEvent = new DidChangeTextDocumentParams(); VersionedTextDocumentIdentifier textDocument = new VersionedTextDocumentIdentifier(); textDocument.setUri(DUMMY_URI); changeEvent.setTextDocument(textDocument); TextDocumentContentChangeEvent contentChange = new TextDocumentContentChangeEvent("<to xmlns=\"http://camel.apache.org/schema/blueprint\" uri=\"\"></to>\n"); changeEvent.setContentChanges(Collections.singletonList(contentChange)); camelLanguageServer.getTextDocumentService().didChange(changeEvent); //check old position doesn't provide completion CompletableFuture<Either<List<CompletionItem>, CompletionList>> completionsAtOldPosition = getCompletionFor(camelLanguageServer, new Position(0, 11)); assertThat(completionsAtOldPosition.get().getLeft()).isEmpty(); //check new position provides completion CompletableFuture<Either<List<CompletionItem>, CompletionList>> completionsAtNewPosition = getCompletionFor(camelLanguageServer, new Position(0, 58)); assertThat(completionsAtNewPosition.get().getLeft()).isNotEmpty(); }
/** * Complete constructor with minimal type information. * * <p>This is important when we're autocompleting new ? with a class that we haven't yet * imported. We don't yet have detailed type information or javadocs, and it's expensive to * retrieve them. So we autocomplete a minimal constructor, and let signature-help fill in the * details. */ private CompletionItem completeConstructor( String packageName, String className, boolean hasTypeParameters) { CompletionItem item = new CompletionItem(); String qualifiedName = packageName.isEmpty() ? className : packageName + "." + className; String key = String.format("%s#<init>", className); String insertText = className; if (hasTypeParameters) insertText += "<>"; insertText += "($0)"; item.setKind(CompletionItemKind.Constructor); item.setLabel(className); item.setDetail(packageName); item.setInsertText(insertText); item.setInsertTextFormat(InsertTextFormat.Snippet); item.setCommand(TRIGGER_SIGNATURE_HELP); item.setFilterText(className); item.setAdditionalTextEdits(addImport(qualifiedName)); item.setSortText("3/" + className); item.setData(key); return item; }
@Test public void addImport() { String file = "/org/javacs/example/AutocompleteOther.java"; // Name of class List<? extends CompletionItem> items = items(file, 9, 17); for (CompletionItem item : items) { if ("ArrayList".equals(item.getLabel())) { assertThat(item.getAdditionalTextEdits(), not(nullValue())); assertThat(item.getAdditionalTextEdits(), not(empty())); return; } } fail("No ArrayList in " + items); }
@Test public void dontImportSamePackage() { String file = "/org/javacs/example/AutocompleteOther.java"; // Name of class List<? extends CompletionItem> items = items(file, 6, 10); for (CompletionItem item : items) { if ("AutocompleteMember".equals(item.getLabel())) { assertThat(item.getAdditionalTextEdits(), either(empty()).or(nullValue())); return; } } fail("No AutocompleteMember in " + items); }
@Test public void dontImportJavaLang() { String file = "/org/javacs/example/AutocompleteOther.java"; // Name of class List<? extends CompletionItem> items = items(file, 11, 38); for (CompletionItem item : items) { if ("ArrayIndexOutOfBoundsException".equals(item.getLabel())) { assertThat(item.getAdditionalTextEdits(), either(empty()).or(nullValue())); return; } } fail("No ArrayIndexOutOfBoundsException in " + items); }
@Test public void dontImportSelf() { String file = "/org/javacs/example/AutocompleteOther.java"; // Name of class List<? extends CompletionItem> items = items(file, 6, 10); for (CompletionItem item : items) { if ("AutocompleteOther".equals(item.getLabel())) { assertThat(item.getAdditionalTextEdits(), either(empty()).or(nullValue())); return; } } fail("No AutocompleteOther in " + items); }
@Test public void dontImportAlreadyImported() { String file = "/org/javacs/example/AutocompleteOther.java"; // Name of class List<? extends CompletionItem> items = items(file, 12, 14); for (CompletionItem item : items) { if ("Arrays".equals(item.getLabel())) { assertThat(item.getAdditionalTextEdits(), either(empty()).or(nullValue())); return; } } fail("No Arrays in " + items); }
@Test public void dontImportAlreadyImportedStar() { String file = "/org/javacs/example/AutocompleteOther.java"; // Name of class List<? extends CompletionItem> items = items(file, 10, 26); for (CompletionItem item : items) { if ("ArrayBlockingQueue".equals(item.getLabel())) { assertThat(item.getAdditionalTextEdits(), either(empty()).or(nullValue())); return; } } fail("No ArrayBlockingQueue in " + items); }
@Test public void autoImportConstructor() throws IOException { String file = "/org/javacs/example/AutocompleteConstructor.java"; // Static methods List<? extends CompletionItem> items = items(file, 6, 19); List<String> suggestions = Lists.transform(items, i -> i.getInsertText()); assertThat(suggestions, hasItems("ArrayList<>($0)")); for (CompletionItem each : items) { if (each.getInsertText().equals("ArrayList<>")) assertThat( "new ? auto-imports", each.getAdditionalTextEdits(), both(not(empty())).and(not(nullValue()))); } }
@Test public void importClass() throws IOException { String file = "/org/javacs/example/AutocompletePackage.java"; // Static methods List<? extends CompletionItem> items = items(file, 4, 25); List<String> suggestions = Lists.transform(items, i -> i.getLabel()); assertThat(suggestions, hasItems("OtherPackagePublic")); assertThat(suggestions, not(hasItems("OtherPackagePrivate"))); for (CompletionItem item : items) { if (item.getLabel().equals("OtherPackagePublic")) assertThat( "Don't import when completing imports", item.getAdditionalTextEdits(), either(empty()).or(nullValue())); } }
@Test public void otherPackageId() throws IOException { String file = "/org/javacs/example/AutocompleteOtherPackage.java"; // Static methods List<? extends CompletionItem> items = items(file, 5, 14); List<String> suggestions = Lists.transform(items, i -> i.getLabel()); assertThat(suggestions, hasItems("OtherPackagePublic")); assertThat(suggestions, not(hasItems("OtherPackagePrivate"))); for (CompletionItem item : items) { if (item.getLabel().equals("OtherPackagePublic")) assertThat( "Auto-import OtherPackagePublic", item.getAdditionalTextEdits(), not(empty())); } }
public synchronized void getCompletions(final SSymbol name, final Set<CompletionItem> results) { for (Variable v : variables) { matchAndAdd(name, v.name, results, CompletionItemKind.Variable); } for (SInvokable m : methods) { matchAndAdd(name, m.getSignature(), results, CompletionItemKind.Method); } for (SlotDefinition s : slots) { matchAndAdd(name, s.getName(), results, CompletionItemKind.Field); } for (MixinDefinition c : classes) { matchAndAdd(name, c.getName(), results, CompletionItemKind.Class); matchAndAdd(name, c.getPrimaryFactorySelector(), results, CompletionItemKind.Constructor); } }
void createTypeProposalLabel(char[] fullName, CompletionItem item) { // only display innermost type name as type name, using any // enclosing types as qualification int qIndex= findSimpleNameStart(fullName); String name = new String(fullName, qIndex, fullName.length - qIndex); StringBuilder nameBuffer= new StringBuilder(); nameBuffer.append(name); if (qIndex > 0) { nameBuffer.append(PACKAGE_NAME_SEPARATOR); nameBuffer.append(new String(fullName,0,qIndex-1)); } item.setFilterText(name); item.setInsertText(name); item.setLabel(nameBuffer.toString()); }
private void createJavadocTypeProposalLabel(char[] fullName, CompletionItem item) { // only display innermost type name as type name, using any // enclosing types as qualification int qIndex= findSimpleNameStart(fullName); StringBuilder nameBuffer= new StringBuilder(); String name = new String(fullName, qIndex, fullName.length - qIndex); nameBuffer.append("{@link "); //$NON-NLS-1$ nameBuffer.append(name); nameBuffer.append('}'); item.setLabel(nameBuffer.toString()); item.setFilterText(name); if (qIndex > 0) { item.setDetail(new String(fullName, 0, qIndex - 1)); } }
@Test public void testRequest() throws Exception { TextDocumentPositionParams p = new TextDocumentPositionParams(); p.setPosition(new Position(1,1)); p.setTextDocument(new TextDocumentIdentifier("test/foo.txt")); CompletionList result = new CompletionList(); result.setIsIncomplete(true); result.setItems(new ArrayList<>()); CompletionItem item = new CompletionItem(); item.setDetail("test"); item.setDocumentation("doc"); item.setFilterText("filter"); item.setInsertText("insert"); item.setKind(CompletionItemKind.Field); result.getItems().add(item); server.expectedRequests.put("textDocument/completion", new Pair<>(p, result)); CompletableFuture<Either<List<CompletionItem>, CompletionList>> future = clientLauncher.getRemoteProxy().getTextDocumentService().completion(p); Assert.assertEquals(Either.forRight(result).toString(), future.get(TIMEOUT, TimeUnit.MILLISECONDS).toString()); client.joinOnEmpty(); }
private void createAnonymousTypeLabel(CompletionProposal proposal, CompletionItem item) { char[] declaringTypeSignature= proposal.getDeclarationSignature(); declaringTypeSignature= Signature.getTypeErasure(declaringTypeSignature); String name = new String(Signature.getSignatureSimpleName(declaringTypeSignature)); item.setInsertText(name); StringBuilder buf= new StringBuilder(); buf.append(name); buf.append('('); appendUnboundedParameterList(buf, proposal); buf.append(')'); buf.append(" "); //$NON-NLS-1$ buf.append("Anonymous Inner Type"); //TODO: consider externalization item.setLabel(buf.toString()); if (proposal.getRequiredProposals() != null) { char[] signatureQualifier= Signature.getSignatureQualifier(declaringTypeSignature); if (signatureQualifier.length > 0) { item.setDetail(String.valueOf(signatureQualifier)); } } setDeclarationSignature(item, String.valueOf(declaringTypeSignature)); }
Either<List<CompletionItem>, CompletionList> completion(TextDocumentPositionParams position, IProgressMonitor monitor) { List<CompletionItem> completionItems = null; try { ICompilationUnit unit = JDTUtils.resolveCompilationUnit(position.getTextDocument().getUri()); completionItems = this.computeContentAssist(unit, position.getPosition().getLine(), position.getPosition().getCharacter(), monitor); } catch (OperationCanceledException ignorable) { // No need to pollute logs when query is cancelled monitor.setCanceled(true); } catch (Exception e) { JavaLanguageServerPlugin.logException("Problem with codeComplete for " + position.getTextDocument().getUri(), e); monitor.setCanceled(true); } CompletionList $ = new CompletionList(); if (monitor.isCanceled()) { $.setIsIncomplete(true); completionItems = null; JavaLanguageServerPlugin.logInfo("Completion request cancelled"); } else { JavaLanguageServerPlugin.logInfo("Completion request completed"); } $.setItems(completionItems == null ? Collections.emptyList() : completionItems); return Either.forRight($); }
@Override public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(TextDocumentPositionParams position) { logInfo(">> document/completion"); CompletionHandler handler = new CompletionHandler(); final IProgressMonitor[] monitors = new IProgressMonitor[1]; CompletableFuture<Either<List<CompletionItem>, CompletionList>> result = computeAsync((cc) -> { monitors[0] = toMonitor(cc); if (Boolean.getBoolean(JAVA_LSP_JOIN_ON_COMPLETION)) { try { Job.getJobManager().join(DocumentLifeCycleHandler.DOCUMENT_LIFE_CYCLE_JOBS, monitors[0]); } catch (OperationCanceledException ignorable) { // No need to pollute logs when query is cancelled } catch (InterruptedException e) { JavaLanguageServerPlugin.logException(e.getMessage(), e); } } return handler.completion(position, monitors[0]); }); result.join(); if (monitors[0].isCanceled()) { result.cancel(true); } return result; }
@Test public void testEquals() { Assert.assertEquals(new TextDocumentIdentifier("foo"), new TextDocumentIdentifier("foo")); Assert.assertNotEquals(new TextDocumentIdentifier("foo"), new TextDocumentIdentifier("bar")); CompletionItem e1 = new CompletionItem(); e1.setAdditionalTextEdits(new ArrayList<>()); e1.getAdditionalTextEdits().add(new TextEdit(new Range(new Position(1,1), new Position(1,1)), "foo")); CompletionItem e2 = new CompletionItem(); e2.setAdditionalTextEdits(new ArrayList<>()); e2.getAdditionalTextEdits().add(new TextEdit(new Range(new Position(1,1), new Position(1,1)), "foo")); CompletionItem e3 = new CompletionItem(); e3.setAdditionalTextEdits(new ArrayList<>()); e3.getAdditionalTextEdits().add(new TextEdit(new Range(new Position(1,1), new Position(1,2)), "foo")); Assert.assertEquals(e1, e2); Assert.assertNotEquals(e1, e3); Assert.assertEquals(e1.hashCode(), e2.hashCode()); Assert.assertNotEquals(e1.hashCode(), e3.hashCode()); }
public void testCompletion_plainTextDoc() throws Exception{ ICompilationUnit unit = getWorkingCopy( //@formatter:off "src/java/Foo.java", "import java.sq \n" + "public class Foo {\n"+ " void foo() {\n"+ " zz\n"+ " }\n\" }\\n\"+"+ "\n"+ "/** This should be <bold>plain</bold>.*/\n" + " void zzz() {}\n"+ "}\n"); //@formatter:off int[] loc = findCompletionLocation(unit, " zz"); CompletionList list = server.completion(JsonMessageHelper.getParams(createCompletionRequest(unit, loc[0], loc[1]))).join().getRight(); assertNotNull(list); assertFalse("No proposals were found", list.getItems().isEmpty()); CompletionItem item = list.getItems().get(0); assertEquals("zzz() : void", item.getLabel()); CompletionItem resolvedItem = server.resolveCompletionItem(item).join(); assertEquals("This should be plain.", resolvedItem.getDocumentation()); }
protected Either<List<CompletionItem>, CompletionList> completion(final CancelIndicator origialCancelIndicator, final TextDocumentPositionParams params) { final LanguageServerImpl.BufferedCancelIndicator cancelIndicator = new LanguageServerImpl.BufferedCancelIndicator(origialCancelIndicator); final URI uri = this._uriExtensions.toUri(params.getTextDocument().getUri()); final IResourceServiceProvider resourceServiceProvider = this.languagesRegistry.getResourceServiceProvider(uri); ContentAssistService _get = null; if (resourceServiceProvider!=null) { _get=resourceServiceProvider.<ContentAssistService>get(ContentAssistService.class); } final ContentAssistService contentAssistService = _get; if ((contentAssistService == null)) { CompletionList _completionList = new CompletionList(); return Either.<List<CompletionItem>, CompletionList>forRight(_completionList); } final Function2<Document, XtextResource, CompletionList> _function = (Document document, XtextResource resource) -> { return contentAssistService.createCompletionList(document, resource, params, cancelIndicator); }; final CompletionList completionList = this.workspaceManager.<CompletionList>doRead(uri, _function); return Either.<List<CompletionItem>, CompletionList>forRight(completionList); }
@Override public CompletableFuture<List<CompletionItem>> getCompletions(CompletableFuture<CamelCatalog> camelCatalog, int positionInCamelUri) { if(getStartPosition() <= positionInCamelUri && positionInCamelUri <= getEndPosition()) { return camelCatalog.thenApply(new CamelComponentSchemaCompletionsFuture()); } else { return CompletableFuture.completedFuture(Collections.emptyList()); } }
@Override public List<CompletionItem> apply(CamelCatalog catalog) { return catalog.findComponentNames().stream() .map(componentName -> ModelHelper.generateComponentModel(catalog.componentJSonSchema(componentName), true)) .map(componentModel -> { CompletionItem completionItem = new CompletionItem(componentModel.getSyntax()); completionItem.setDocumentation(componentModel.getDescription()); return completionItem; }).collect(Collectors.toList()); }
@Override public List<CompletionItem> apply(CamelCatalog camelCatalog) { Optional<EndpointOptionModel> endpointModel = retrieveEndpointOptionModel(camelCatalog); if(endpointModel.isPresent()) { EndpointOptionModel endpointOptionModel = endpointModel.get(); String enums = endpointOptionModel.getEnums(); if (enums != null && !enums.isEmpty()) { return computeCompletionForEnums(enums); } else if(BOOLEAN_TYPE.equals(endpointOptionModel.getType())) { return Arrays.asList(new CompletionItem(Boolean.TRUE.toString()), new CompletionItem(Boolean.FALSE.toString())); } } return Collections.emptyList(); }
private List<CompletionItem> computeCompletionForEnums(String enums) { List<CompletionItem> completionItems = new ArrayList<>(); for(String enumValue : enums.split(",")) { completionItems.add(new CompletionItem(enumValue)); } return completionItems; }
@Test public void testProvideCompletionForCamelBlueprintNamespace() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer("<from uri=\"\" xmlns=\"http://camel.apache.org/schema/blueprint\"></from>\n"); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(0, 11)); assertThat(completions.get().getLeft()).contains(expectedAhcCompletioncompletionItem); }
@Test public void testProvideCompletionForToCamelBlueprintNamespace() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer("<to uri=\"\" xmlns=\"http://camel.apache.org/schema/blueprint\"></to>\n"); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(0, 9)); assertThat(completions.get().getLeft()).contains(expectedAhcCompletioncompletionItem); }
@Test public void testProvideCompletionForCamelSpringNamespace() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer("<from uri=\"\" xmlns=\"http://camel.apache.org/schema/spring\"></from>\n"); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(0, 11)); assertThat(completions.get().getLeft()).contains(expectedAhcCompletioncompletionItem); }
@Test public void testProvideCompletionforMultiline() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer( "<camelContext xmlns=\"http://camel.apache.org/schema/spring\">\n" + "<to uri=\"\" ></to>\n" + "</camelContext>"); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(1, 9)); assertThat(completions.get().getLeft()).contains(expectedAhcCompletioncompletionItem); }
@Test public void testDONTProvideCompletionForNotCamelnamespace() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer("<from uri=\"\"></from>\n"); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(0, 11)); assertThat(completions.get().getLeft()).isEmpty(); assertThat(completions.get().getRight()).isNull(); }
@Test public void testDONTProvideCompletionWhenNotAfterURIEqualQuote() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer("<from uri=\"\" xmlns=\"http://camel.apache.org/schema/spring\"></from>\n"); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(0, 6)); assertThat(completions.get().getLeft()).isEmpty(); assertThat(completions.get().getRight()).isNull(); }
private void testProvideCamelOptions(String textTotest, int line, int character) throws URISyntaxException, InterruptedException, ExecutionException { CamelLanguageServer camelLanguageServer = initializeLanguageServer(textTotest); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(line, character)); assertThat(completions.get().getLeft()).contains( new CompletionItem("true"), new CompletionItem("false")); }
@Test public void testProvideCompletionForCamelBlueprintNamespace() throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer(textToTest); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(line, character)); if(shouldHaveCompletion) { assertThat(completions.get().getLeft()).contains(expectedAhcCompletioncompletionItem); } else { assertThat(completions.get().getLeft()).doesNotContain(expectedAhcCompletioncompletionItem); assertThat(completions.get().getRight()).isNull(); } }
private void testProvideCamelOptions(String textTotest, int line, int character) throws URISyntaxException, InterruptedException, ExecutionException { CamelLanguageServer camelLanguageServer = initializeLanguageServer(textTotest); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = getCompletionFor(camelLanguageServer, new Position(line, character)); assertThat(completions.get().getLeft()).contains( new CompletionItem("InOnly"), new CompletionItem("RobustInOnly"), new CompletionItem("InOut"), new CompletionItem("InOptionalOut"), new CompletionItem("OutOnly"), new CompletionItem("RobustOutOnly"), new CompletionItem("OutIn"), new CompletionItem("OutOptionalIn")); }
protected CompletableFuture<Either<List<CompletionItem>, CompletionList>> getCompletionFor(CamelLanguageServer camelLanguageServer, Position position) { TextDocumentService textDocumentService = camelLanguageServer.getTextDocumentService(); TextDocumentPositionParams dummyCompletionPositionRequest = new TextDocumentPositionParams(new TextDocumentIdentifier(DUMMY_URI), position); CompletableFuture<Either<List<CompletionItem>, CompletionList>> completions = textDocumentService.completion(dummyCompletionPositionRequest); return completions; }
/** Suggest constructors that haven't yet been imported, but are on the source or class path */ private Stream<CompletionItem> notImportedConstructors(String partialIdentifier, Scope scope) { String packageName = packageName(scope); Stream<CompletionItem> fromSourcePath = accessibleSourcePathClasses(partialIdentifier, scope) .filter(c -> c.hasAccessibleConstructor(packageName)) .map(this::completeConstructorFromSourcePath); Stream<CompletionItem> fromClassPath = accessibleClassPathClasses(partialIdentifier, scope) .filter(c -> classPath.hasAccessibleConstructor(c, packageName)) .map(c -> completeConstructorFromClassPath(c.load())); // TODO remove class path classes that are also available from source path return Stream.concat(fromSourcePath, fromClassPath); }
/** Suggest classes that haven't yet been imported, but are on the source or class path */ private Stream<CompletionItem> notImportedClasses(String partialIdentifier, Scope scope) { Stream<String> fromSourcePath = accessibleSourcePathClasses(partialIdentifier, scope).map(c -> c.qualifiedName()); Stream<String> fromClassPath = accessibleClassPathClasses(partialIdentifier, scope) .map(c -> c.getName()) .filter(name -> !sourcePath.isTopLevelClass(name)); return Stream.concat(fromSourcePath, fromClassPath) .map(this::completeClassNameFromClassPath); }