Search in sources :

Example 1 with SnippetCompletionProposal

use of org.eclipse.jdt.ls.core.internal.contentassist.SnippetCompletionProposal 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)

Aggregations

UncheckedTimeoutException (com.google.common.util.concurrent.UncheckedTimeoutException)1 Reader (java.io.Reader)1 TimeoutException (java.util.concurrent.TimeoutException)1 CompletionContext (org.eclipse.jdt.core.CompletionContext)1 CompletionProposal (org.eclipse.jdt.core.CompletionProposal)1 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)1 IField (org.eclipse.jdt.core.IField)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 JavaModelException (org.eclipse.jdt.core.JavaModelException)1 SourceRange (org.eclipse.jdt.core.SourceRange)1 InternalCompletionProposal (org.eclipse.jdt.internal.codeassist.InternalCompletionProposal)1 Binding (org.eclipse.jdt.internal.compiler.lookup.Binding)1 MethodBinding (org.eclipse.jdt.internal.compiler.lookup.MethodBinding)1 CompletionProposalReplacementProvider (org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalReplacementProvider)1 SnippetCompletionProposal (org.eclipse.jdt.ls.core.internal.contentassist.SnippetCompletionProposal)1