Search in sources :

Example 1 with MarkupContent

use of org.eclipse.lsp4j.MarkupContent in project eclipse.jdt.ls by eclipse.

the class CompletionResolveHandler method resolve.

public CompletionItem resolve(CompletionItem param, IProgressMonitor monitor) {
    @SuppressWarnings("unchecked") Map<String, String> data = JSONUtility.toModel(param.getData(), Map.class);
    // clean resolve data
    param.setData(null);
    if (!CompletionProposalRequestor.SUPPORTED_KINDS.contains(param.getKind()) || data == null || !data.containsKey(DATA_FIELD_URI) || !data.containsKey(DATA_FIELD_REQUEST_ID) || !data.containsKey(DATA_FIELD_PROPOSAL_ID)) {
        return param;
    }
    int proposalId = Integer.parseInt(data.get(DATA_FIELD_PROPOSAL_ID));
    long requestId = Long.parseLong(data.get(DATA_FIELD_REQUEST_ID));
    CompletionResponse completionResponse = CompletionResponses.get(requestId);
    if (completionResponse == null || completionResponse.getProposals().size() <= proposalId) {
        throw new IllegalStateException("Invalid completion proposal");
    }
    String uri = data.get(DATA_FIELD_URI);
    ICompilationUnit unit = JDTUtils.resolveCompilationUnit(uri);
    if (unit == null) {
        throw new IllegalStateException(NLS.bind("Unable to match Compilation Unit from {0} ", uri));
    }
    if (monitor.isCanceled()) {
        param.setData(null);
        return param;
    }
    // generic snippets
    if (param.getKind() == CompletionItemKind.Snippet) {
        try {
            CompletionContext ctx = completionResponse.getContext();
            CompletionProposal proposal = completionResponse.getProposals().get(proposalId);
            Template template = ((SnippetCompletionProposal) proposal).getTemplate();
            String content = SnippetCompletionProposal.evaluateGenericTemplate(unit, ctx, template);
            Range range = JDTUtils.toRange(unit, ctx.getOffset(), 0);
            TextEdit textEdit = new TextEdit(range, content);
            param.setTextEdit(Either.forLeft(textEdit));
            param.setDocumentation(SnippetUtils.beautifyDocument(content));
            param.setData(null);
        } catch (JavaModelException e) {
            JavaLanguageServerPlugin.logException(e.getMessage(), e);
        }
        return param;
    }
    if (manager.getClientPreferences().isResolveAdditionalTextEditsSupport()) {
        CompletionProposalReplacementProvider proposalProvider = new CompletionProposalReplacementProvider(unit, completionResponse.getContext(), completionResponse.getOffset(), manager.getPreferences(), manager.getClientPreferences());
        proposalProvider.updateAdditionalTextEdits(completionResponse.getProposals().get(proposalId), param, '\0');
    }
    if (data.containsKey(DATA_FIELD_DECLARATION_SIGNATURE)) {
        String typeName = stripSignatureToFQN(String.valueOf(data.get(DATA_FIELD_DECLARATION_SIGNATURE)));
        try {
            IMember member = null;
            IType type = unit.getJavaProject().findType(typeName);
            CompletionProposal proposal = completionResponse.getProposals().get(proposalId);
            if (type != null && data.containsKey(DATA_FIELD_NAME)) {
                String name = data.get(DATA_FIELD_NAME);
                String[] paramSigs = CharOperation.NO_STRINGS;
                if (data.containsKey(DATA_FIELD_SIGNATURE)) {
                    if (proposal instanceof InternalCompletionProposal) {
                        Binding binding = ((InternalCompletionProposal) proposal).getBinding();
                        if (binding instanceof MethodBinding) {
                            MethodBinding methodBinding = (MethodBinding) binding;
                            MethodBinding original = methodBinding.original();
                            char[] signature;
                            if (original != binding) {
                                signature = Engine.getSignature(original);
                            } else {
                                signature = Engine.getSignature(methodBinding);
                            }
                            String[] parameters = Signature.getParameterTypes(String.valueOf(fix83600(signature)));
                            for (int i = 0; i < parameters.length; i++) {
                                parameters[i] = getLowerBound(parameters[i]);
                            }
                            paramSigs = parameters;
                        }
                    }
                }
                IMethod method = type.getMethod(name, paramSigs);
                IMethod[] methods = type.findMethods(method);
                if (methods != null && methods.length > 0) {
                    method = methods[0];
                }
                if (method.exists()) {
                    member = method;
                } else {
                    IField field = type.getField(name);
                    if (field.exists()) {
                        member = field;
                    }
                }
            } else {
                member = type;
            }
            if (member != null && member.exists() && !monitor.isCanceled()) {
                String javadoc = null;
                try {
                    final IMember curMember = member;
                    javadoc = SimpleTimeLimiter.create(Executors.newCachedThreadPool()).callWithTimeout(() -> {
                        Reader reader;
                        if (manager.getClientPreferences().isSupportsCompletionDocumentationMarkdown()) {
                            reader = JavadocContentAccess2.getMarkdownContentReader(curMember);
                        } else {
                            reader = JavadocContentAccess.getPlainTextContentReader(curMember);
                        }
                        return reader == null ? null : CharStreams.toString(reader);
                    }, 500, TimeUnit.MILLISECONDS);
                } catch (UncheckedTimeoutException | TimeoutException tooSlow) {
                    // Ignore error for now as it's spamming clients on content assist.
                    // TODO cache javadoc resolution results?
                    // JavaLanguageServerPlugin.logError("Unable to get documentation under 500ms");
                    monitor.setCanceled(true);
                } catch (Exception e) {
                    JavaLanguageServerPlugin.logException("Unable to read documentation", e);
                    monitor.setCanceled(true);
                }
                String constantValue = null;
                if (proposal.getKind() == CompletionProposal.FIELD_REF) {
                    try {
                        IField field = JDTUtils.resolveField(proposal, unit.getJavaProject());
                        Region nameRegion = null;
                        if (field != null) {
                            ITypeRoot typeRoot = field.getTypeRoot();
                            ISourceRange nameRange = ((ISourceReference) field).getNameRange();
                            if (SourceRange.isAvailable(nameRange)) {
                                nameRegion = new Region(nameRange.getOffset(), nameRange.getLength());
                            }
                            constantValue = JDTUtils.getConstantValue(field, typeRoot, nameRegion);
                        }
                    } catch (JavaModelException e) {
                        JavaLanguageServerPlugin.log(e);
                    }
                }
                if (constantValue != null) {
                    if (manager.getClientPreferences().isSupportsCompletionDocumentationMarkdown()) {
                        javadoc = (javadoc == null ? EMPTY_STRING : javadoc) + "\n\n" + VALUE + constantValue;
                    } else {
                        javadoc = (javadoc == null ? EMPTY_STRING : javadoc) + VALUE + constantValue;
                    }
                }
                String defaultValue = null;
                if (proposal.getKind() == CompletionProposal.METHOD_REF || proposal.getKind() == CompletionProposal.ANNOTATION_ATTRIBUTE_REF) {
                    try {
                        IMethod method = JDTUtils.resolveMethod(proposal, unit.getJavaProject());
                        Region nameRegion = null;
                        if (method != null) {
                            ITypeRoot typeRoot = method.getTypeRoot();
                            ISourceRange nameRange = ((ISourceReference) method).getNameRange();
                            if (SourceRange.isAvailable(nameRange)) {
                                nameRegion = new Region(nameRange.getOffset(), nameRange.getLength());
                            }
                            defaultValue = JDTUtils.getAnnotationMemberDefaultValue(method, typeRoot, nameRegion);
                        }
                    } catch (JavaModelException e) {
                        JavaLanguageServerPlugin.log(e);
                    }
                }
                if (defaultValue != null) {
                    if (manager.getClientPreferences().isSupportsCompletionDocumentationMarkdown()) {
                        javadoc = (javadoc == null ? EMPTY_STRING : javadoc) + "\n\n" + DEFAULT + defaultValue;
                    } else {
                        javadoc = (javadoc == null ? EMPTY_STRING : javadoc) + DEFAULT + defaultValue;
                    }
                }
                if (javadoc != null) {
                    if (manager.getClientPreferences().isSupportsCompletionDocumentationMarkdown()) {
                        MarkupContent markupContent = new MarkupContent();
                        markupContent.setKind(MarkupKind.MARKDOWN);
                        markupContent.setValue(javadoc);
                        param.setDocumentation(markupContent);
                    } else {
                        param.setDocumentation(javadoc);
                    }
                }
            }
        } catch (JavaModelException e) {
            JavaLanguageServerPlugin.logException("Unable to resolve compilation", e);
            monitor.setCanceled(true);
        }
    }
    if (monitor.isCanceled()) {
        param.setData(null);
    }
    return param;
}
Also used : JavaModelException(org.eclipse.jdt.core.JavaModelException) Reader(java.io.Reader) UncheckedTimeoutException(com.google.common.util.concurrent.UncheckedTimeoutException) IMember(org.eclipse.jdt.core.IMember) Template(org.eclipse.jface.text.templates.Template) IType(org.eclipse.jdt.core.IType) InternalCompletionProposal(org.eclipse.jdt.internal.codeassist.InternalCompletionProposal) CompletionProposalReplacementProvider(org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalReplacementProvider) MethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) SnippetCompletionProposal(org.eclipse.jdt.ls.core.internal.contentassist.SnippetCompletionProposal) IMethod(org.eclipse.jdt.core.IMethod) TimeoutException(java.util.concurrent.TimeoutException) UncheckedTimeoutException(com.google.common.util.concurrent.UncheckedTimeoutException) ISourceRange(org.eclipse.jdt.core.ISourceRange) MethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) Binding(org.eclipse.jdt.internal.compiler.lookup.Binding) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) SnippetCompletionProposal(org.eclipse.jdt.ls.core.internal.contentassist.SnippetCompletionProposal) InternalCompletionProposal(org.eclipse.jdt.internal.codeassist.InternalCompletionProposal) CompletionProposal(org.eclipse.jdt.core.CompletionProposal) ITypeRoot(org.eclipse.jdt.core.ITypeRoot) ISourceRange(org.eclipse.jdt.core.ISourceRange) Range(org.eclipse.lsp4j.Range) SourceRange(org.eclipse.jdt.core.SourceRange) IField(org.eclipse.jdt.core.IField) MarkupContent(org.eclipse.lsp4j.MarkupContent) TimeoutException(java.util.concurrent.TimeoutException) JavaModelException(org.eclipse.jdt.core.JavaModelException) UncheckedTimeoutException(com.google.common.util.concurrent.UncheckedTimeoutException) CompletionContext(org.eclipse.jdt.core.CompletionContext) TextEdit(org.eclipse.lsp4j.TextEdit) Region(org.eclipse.jface.text.Region) ISourceReference(org.eclipse.jdt.core.ISourceReference)

Example 2 with MarkupContent

use of org.eclipse.lsp4j.MarkupContent in project eclipse.jdt.ls by eclipse.

the class SnippetUtils method beautifyDocument.

public static Either<String, MarkupContent> beautifyDocument(String raw) {
    // remove the placeholder for the plain cursor like: ${0}, ${1:variable}
    String escapedString = raw.replaceAll("\\$\\{\\d:?(.*?)\\}", "$1");
    // Replace the reserved variable with empty string.
    // See: https://github.com/eclipse/eclipse.jdt.ls/issues/1220
    escapedString = escapedString.replaceAll(TM_SELECTED_TEXT, "");
    if (JavaLanguageServerPlugin.getPreferencesManager() != null && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences() != null && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isSupportsCompletionDocumentationMarkdown()) {
        MarkupContent markupContent = new MarkupContent();
        markupContent.setKind(MarkupKind.MARKDOWN);
        markupContent.setValue(String.format("```%s\n%s\n```", MARKDOWN_LANGUAGE, escapedString));
        return Either.forRight(markupContent);
    } else {
        return Either.forLeft(escapedString);
    }
}
Also used : MarkupContent(org.eclipse.lsp4j.MarkupContent)

Example 3 with MarkupContent

use of org.eclipse.lsp4j.MarkupContent in project eclipse.jdt.ls by eclipse.

the class SnippetUtilsTest method testComplicatedInput.

@Test
public void testComplicatedInput() {
    ClientPreferences mockCapabilies = mock(ClientPreferences.class);
    when(mockCapabilies.isSupportsCompletionDocumentationMarkdown()).thenReturn(Boolean.FALSE);
    when(preferenceManager.getClientPreferences()).thenReturn(mockCapabilies);
    // @formatter:off
    String raw = "/**\n" + " * ${1:A}\n" + " */\n" + "public class ${1:A} {\n" + "\n" + "\t${0}\n" + "}";
    // @formatter:on
    Either<String, MarkupContent> result = SnippetUtils.beautifyDocument(raw);
    // @formatter:off
    String expected = "/**\n" + " * A\n" + " */\n" + "public class A {\n" + "\n" + "\t\n" + "}";
    // @formatter:on
    assertEquals(result.getLeft(), expected);
}
Also used : ClientPreferences(org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences) MarkupContent(org.eclipse.lsp4j.MarkupContent) Test(org.junit.Test)

Example 4 with MarkupContent

use of org.eclipse.lsp4j.MarkupContent in project eclipse.jdt.ls by eclipse.

the class CompletionHandlerTest method testCompletion_javadocMarkdown.

@Test
public void testCompletion_javadocMarkdown() throws Exception {
    IJavaProject javaProject = JavaCore.create(project);
    ClientPreferences mockCapabilies = Mockito.mock(ClientPreferences.class);
    Mockito.when(preferenceManager.getClientPreferences()).thenReturn(mockCapabilies);
    Mockito.when(mockCapabilies.isSupportsCompletionDocumentationMarkdown()).thenReturn(true);
    ICompilationUnit unit = (ICompilationUnit) javaProject.findElement(new Path("org/sample/TestJavadoc.java"));
    unit.becomeWorkingCopy(null);
    String joinOnCompletion = System.getProperty(JDTLanguageServer.JAVA_LSP_JOIN_ON_COMPLETION);
    try {
        System.setProperty(JDTLanguageServer.JAVA_LSP_JOIN_ON_COMPLETION, "true");
        int[] loc = findCompletionLocation(unit, "inner.");
        CompletionParams position = JsonMessageHelper.getParams(createCompletionRequest(unit, loc[0], loc[1]));
        String source = unit.getSource();
        changeDocument(unit, source, 3);
        Job.getJobManager().join(DocumentLifeCycleHandler.DOCUMENT_LIFE_CYCLE_JOBS, new NullProgressMonitor());
        changeDocument(unit, source, 4);
        CompletionList list = server.completion(position).join().getRight();
        CompletionItem resolved = server.resolveCompletionItem(list.getItems().get(0)).join();
        MarkupContent markup = resolved.getDocumentation().getRight();
        assertNotNull(markup);
        assertEquals(MarkupKind.MARKDOWN, markup.getKind());
        assertEquals("Test", markup.getValue());
    } finally {
        unit.discardWorkingCopy();
        if (joinOnCompletion == null) {
            System.clearProperty(JDTLanguageServer.JAVA_LSP_JOIN_ON_COMPLETION);
        } else {
            System.setProperty(JDTLanguageServer.JAVA_LSP_JOIN_ON_COMPLETION, joinOnCompletion);
        }
    }
}
Also used : Path(org.eclipse.core.runtime.Path) ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) NullProgressMonitor(org.eclipse.core.runtime.NullProgressMonitor) CompletionList(org.eclipse.lsp4j.CompletionList) IJavaProject(org.eclipse.jdt.core.IJavaProject) ClientPreferences(org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences) CompletionParams(org.eclipse.lsp4j.CompletionParams) CompletionItem(org.eclipse.lsp4j.CompletionItem) MarkupContent(org.eclipse.lsp4j.MarkupContent) Test(org.junit.Test)

Example 5 with MarkupContent

use of org.eclipse.lsp4j.MarkupContent in project xtext-core by eclipse.

the class HoverService method hover.

protected Hover hover(HoverContext context) {
    if (context == null) {
        return IHoverService.EMPTY_HOVER;
    }
    MarkupContent contents = getMarkupContent(context);
    if (contents == null) {
        return IHoverService.EMPTY_HOVER;
    }
    Range range = getRange(context);
    if (range == null) {
        return IHoverService.EMPTY_HOVER;
    }
    return new Hover(contents, range);
}
Also used : Hover(org.eclipse.lsp4j.Hover) Range(org.eclipse.lsp4j.Range) MarkupContent(org.eclipse.lsp4j.MarkupContent)

Aggregations

MarkupContent (org.eclipse.lsp4j.MarkupContent)9 ClientPreferences (org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences)6 Test (org.junit.Test)6 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)2 Range (org.eclipse.lsp4j.Range)2 UncheckedTimeoutException (com.google.common.util.concurrent.UncheckedTimeoutException)1 Reader (java.io.Reader)1 TimeoutException (java.util.concurrent.TimeoutException)1 NullProgressMonitor (org.eclipse.core.runtime.NullProgressMonitor)1 Path (org.eclipse.core.runtime.Path)1 CompletionContext (org.eclipse.jdt.core.CompletionContext)1 CompletionProposal (org.eclipse.jdt.core.CompletionProposal)1 IField (org.eclipse.jdt.core.IField)1 IJavaProject (org.eclipse.jdt.core.IJavaProject)1 IMember (org.eclipse.jdt.core.IMember)1 IMethod (org.eclipse.jdt.core.IMethod)1 ISourceRange (org.eclipse.jdt.core.ISourceRange)1 ISourceReference (org.eclipse.jdt.core.ISourceReference)1 IType (org.eclipse.jdt.core.IType)1 ITypeRoot (org.eclipse.jdt.core.ITypeRoot)1