From 351c3808f39d224e9546d95bc6a4a16ca6e60d19 Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Tue, 7 Aug 2018 17:46:54 -0400 Subject: [PATCH] WIP Add support of the "deprecated" property ... for CompletionItems, Workspace and Document symbols Signed-off-by: Fred Bricon --- .../CompletionProposalRequestor.java | 128 +++++++++++------- .../internal/handlers/CompletionHandler.java | 4 + .../handlers/DocumentSymbolHandler.java | 72 +++++----- .../internal/handlers/JDTLanguageServer.java | 5 +- .../handlers/WorkspaceSymbolHandler.java | 15 +- .../preferences/ClientPreferences.java | 12 ++ .../preferences/PreferenceManager.java | 6 + .../handlers/DocumentSymbolHandlerTest.java | 4 +- 8 files changed, 152 insertions(+), 94 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java index 5794b749f3..c4a15a94bd 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java @@ -55,6 +55,7 @@ public final class CompletionProposalRequestor extends CompletionRequestor { private CompletionResponse response; private boolean fIsTestCodeExcluded; private CompletionContext context; + private boolean deprecatedSupported; // Update SUPPORTED_KINDS when mapKind changes // @formatter:off @@ -140,6 +141,9 @@ public CompletionItem toCompletionItem(CompletionProposal proposal, int index) { data.put(CompletionResolveHandler.DATA_FIELD_REQUEST_ID, String.valueOf(response.getId())); data.put(CompletionResolveHandler.DATA_FIELD_PROPOSAL_ID, String.valueOf(index)); $.setData(data); + if (deprecatedSupported) { + $.setDeprecated(isDeprecated(proposal)); + } this.descriptionProvider.updateDescription(proposal, $); $.setSortText(SortTextHelper.computeSortText(proposal)); if (proposal.getKind() == CompletionProposal.FIELD_REF) { @@ -195,64 +199,63 @@ public void acceptContext(CompletionContext context) { this.descriptionProvider = new CompletionProposalDescriptionProvider(context); } - private CompletionItemKind mapKind(final CompletionProposal proposal) { //When a new CompletionItemKind is added, don't forget to update SUPPORTED_KINDS int kind = proposal.getKind(); int flags = proposal.getFlags(); switch (kind) { - case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION: - case CompletionProposal.CONSTRUCTOR_INVOCATION: - return CompletionItemKind.Constructor; - case CompletionProposal.ANONYMOUS_CLASS_DECLARATION: - case CompletionProposal.TYPE_REF: - if (Flags.isInterface(flags)) { - return CompletionItemKind.Interface; - } else if (Flags.isEnum(flags)) { - return CompletionItemKind.Enum; - } - return CompletionItemKind.Class; - case CompletionProposal.FIELD_IMPORT: - case CompletionProposal.METHOD_IMPORT: - case CompletionProposal.METHOD_NAME_REFERENCE: - case CompletionProposal.PACKAGE_REF: - case CompletionProposal.TYPE_IMPORT: - case CompletionProposal.MODULE_DECLARATION: - case CompletionProposal.MODULE_REF: - return CompletionItemKind.Module; - case CompletionProposal.FIELD_REF: - if (Flags.isEnum(flags)) { - return CompletionItemKind.EnumMember; - } - if (Flags.isStatic(flags) && Flags.isFinal(flags)) { - return CompletionItemKind.Constant; - } - return CompletionItemKind.Field; - case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER: - return CompletionItemKind.Field; - case CompletionProposal.KEYWORD: - return CompletionItemKind.Keyword; - case CompletionProposal.LABEL_REF: - return CompletionItemKind.Reference; - case CompletionProposal.LOCAL_VARIABLE_REF: - case CompletionProposal.VARIABLE_DECLARATION: - return CompletionItemKind.Variable; - case CompletionProposal.METHOD_DECLARATION: - case CompletionProposal.METHOD_REF: - case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER: - case CompletionProposal.POTENTIAL_METHOD_DECLARATION: - return CompletionItemKind.Method; + case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION: + case CompletionProposal.CONSTRUCTOR_INVOCATION: + return CompletionItemKind.Constructor; + case CompletionProposal.ANONYMOUS_CLASS_DECLARATION: + case CompletionProposal.TYPE_REF: + if (Flags.isInterface(flags)) { + return CompletionItemKind.Interface; + } else if (Flags.isEnum(flags)) { + return CompletionItemKind.Enum; + } + return CompletionItemKind.Class; + case CompletionProposal.FIELD_IMPORT: + case CompletionProposal.METHOD_IMPORT: + case CompletionProposal.METHOD_NAME_REFERENCE: + case CompletionProposal.PACKAGE_REF: + case CompletionProposal.TYPE_IMPORT: + case CompletionProposal.MODULE_DECLARATION: + case CompletionProposal.MODULE_REF: + return CompletionItemKind.Module; + case CompletionProposal.FIELD_REF: + if (Flags.isEnum(flags)) { + return CompletionItemKind.EnumMember; + } + if (Flags.isStatic(flags) && Flags.isFinal(flags)) { + return CompletionItemKind.Constant; + } + return CompletionItemKind.Field; + case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER: + return CompletionItemKind.Field; + case CompletionProposal.KEYWORD: + return CompletionItemKind.Keyword; + case CompletionProposal.LABEL_REF: + return CompletionItemKind.Reference; + case CompletionProposal.LOCAL_VARIABLE_REF: + case CompletionProposal.VARIABLE_DECLARATION: + return CompletionItemKind.Variable; + case CompletionProposal.METHOD_DECLARATION: + case CompletionProposal.METHOD_REF: + case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER: + case CompletionProposal.POTENTIAL_METHOD_DECLARATION: + return CompletionItemKind.Method; //text - case CompletionProposal.ANNOTATION_ATTRIBUTE_REF: - case CompletionProposal.JAVADOC_BLOCK_TAG: - case CompletionProposal.JAVADOC_FIELD_REF: - case CompletionProposal.JAVADOC_INLINE_TAG: - case CompletionProposal.JAVADOC_METHOD_REF: - case CompletionProposal.JAVADOC_PARAM_REF: - case CompletionProposal.JAVADOC_TYPE_REF: - case CompletionProposal.JAVADOC_VALUE_REF: - default: - return CompletionItemKind.Text; + case CompletionProposal.ANNOTATION_ATTRIBUTE_REF: + case CompletionProposal.JAVADOC_BLOCK_TAG: + case CompletionProposal.JAVADOC_FIELD_REF: + case CompletionProposal.JAVADOC_INLINE_TAG: + case CompletionProposal.JAVADOC_METHOD_REF: + case CompletionProposal.JAVADOC_PARAM_REF: + case CompletionProposal.JAVADOC_TYPE_REF: + case CompletionProposal.JAVADOC_VALUE_REF: + default: + return CompletionItemKind.Text; } } @@ -359,4 +362,25 @@ protected final char[] getDeclaringType(CompletionProposal proposal) { } } + public boolean isDeprecated(CompletionProposal proposal) { + int flags = proposal.getFlags(); + boolean deprecated = Flags.isDeprecated(flags); + if (!deprecated) { + CompletionProposal[] requiredProposals = proposal.getRequiredProposals(); + if (requiredProposals != null) { + for (int i = 0; i < requiredProposals.length; i++) { + CompletionProposal requiredProposal = requiredProposals[i]; + if (requiredProposal.getKind() == CompletionProposal.TYPE_REF) { + deprecated |= Flags.isDeprecated(requiredProposal.getFlags()); + } + } + } + } + return deprecated; + } + + public void addDeprecatedProperty(boolean addDeprecatedProperty) { + this.deprecatedSupported = addDeprecatedProperty; + } + } \ No newline at end of file diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java index 0548e07aa6..88471f3030 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java @@ -91,6 +91,10 @@ private List computeContentAssist(ICompilationUnit unit, int lin collector.setAllowsRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF, true); collector.setFavoriteReferences(getFavoriteStaticMembers()); + PreferenceManager preferenceManager = JavaLanguageServerPlugin.getPreferencesManager(); + if (preferenceManager != null) { + collector.addDeprecatedProperty(preferenceManager.isClientSupportsDeprecated()); + } if (offset >-1 && !monitor.isCanceled()) { IBuffer buffer = unit.getBuffer(); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandler.java index 043f6891f4..69e87ad4fd 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandler.java @@ -59,9 +59,11 @@ public class DocumentSymbolHandler { private static Range DEFAULT_RANGE = new Range(new Position(0, 0), new Position(0, 0)); private boolean hierarchicalDocumentSymbolSupported; + private boolean deprecatedSupported; - public DocumentSymbolHandler(boolean hierarchicalDocumentSymbolSupported) { + public DocumentSymbolHandler(boolean hierarchicalDocumentSymbolSupported, boolean deprecatedSupported) { this.hierarchicalDocumentSymbolSupported = hierarchicalDocumentSymbolSupported; + this.deprecatedSupported = deprecatedSupported; } public List> documentSymbol(DocumentSymbolParams params, IProgressMonitor monitor) { @@ -151,7 +153,9 @@ private DocumentSymbol toDocumentSymbol(IJavaElement unit, IProgressMonitor moni symbol.setRange(getRange(unit)); symbol.setSelectionRange(getSelectionRange(unit)); symbol.setKind(mapKind(unit)); - symbol.setDeprecated(isDeprecated(unit)); + if (deprecatedSupported) { + symbol.setDeprecated(isDeprecated(unit)); + } symbol.setDetail(getDetail(unit, name)); if (unit instanceof IParent) { //@formatter:off @@ -243,39 +247,39 @@ else if (type.isEnum()) { } catch (JavaModelException ignore) { } return SymbolKind.Class; - case IJavaElement.ANNOTATION: - return SymbolKind.Property; // TODO: find a better mapping - case IJavaElement.CLASS_FILE: - case IJavaElement.COMPILATION_UNIT: - return SymbolKind.File; - case IJavaElement.FIELD: - IField field = (IField) element; - try { - if (field.isEnumConstant()) { - return SymbolKind.EnumMember; - } - int flags = field.getFlags(); - if (Flags.isStatic(flags) && Flags.isFinal(flags)) { - return SymbolKind.Constant; + case IJavaElement.ANNOTATION: + return SymbolKind.Property; // TODO: find a better mapping + case IJavaElement.CLASS_FILE: + case IJavaElement.COMPILATION_UNIT: + return SymbolKind.File; + case IJavaElement.FIELD: + IField field = (IField) element; + try { + if (field.isEnumConstant()) { + return SymbolKind.EnumMember; + } + int flags = field.getFlags(); + if (Flags.isStatic(flags) && Flags.isFinal(flags)) { + return SymbolKind.Constant; + } + } catch (JavaModelException ignore) { } - } catch (JavaModelException ignore) { - } - return SymbolKind.Field; - case IJavaElement.IMPORT_CONTAINER: - case IJavaElement.IMPORT_DECLARATION: - //should we return SymbolKind.Namespace? - case IJavaElement.JAVA_MODULE: - return SymbolKind.Module; - case IJavaElement.INITIALIZER: - return SymbolKind.Constructor; - case IJavaElement.LOCAL_VARIABLE: - return SymbolKind.Variable; - case IJavaElement.TYPE_PARAMETER: - return SymbolKind.TypeParameter; - case IJavaElement.METHOD: - return SymbolKind.Method; - case IJavaElement.PACKAGE_DECLARATION: - return SymbolKind.Package; + return SymbolKind.Field; + case IJavaElement.IMPORT_CONTAINER: + case IJavaElement.IMPORT_DECLARATION: + //should we return SymbolKind.Namespace? + case IJavaElement.JAVA_MODULE: + return SymbolKind.Module; + case IJavaElement.INITIALIZER: + return SymbolKind.Constructor; + case IJavaElement.LOCAL_VARIABLE: + return SymbolKind.Variable; + case IJavaElement.TYPE_PARAMETER: + return SymbolKind.TypeParameter; + case IJavaElement.METHOD: + return SymbolKind.Method; + case IJavaElement.PACKAGE_DECLARATION: + return SymbolKind.Package; } return SymbolKind.String; } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java index 769f3aa5a6..9e3ffde450 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java @@ -584,9 +584,10 @@ public CompletableFuture> documentHighlight(Te @Override public CompletableFuture>> documentSymbol(DocumentSymbolParams params) { logInfo(">> document/documentSymbol"); - boolean hierarchicalDocumentSymbolSupported = preferenceManager.getClientPreferences().isHierarchicalDocumentSymbolSupported(); - DocumentSymbolHandler handler = new DocumentSymbolHandler(hierarchicalDocumentSymbolSupported); return computeAsync((monitor) -> { + boolean hierarchicalDocumentSymbolSupported = preferenceManager.getClientPreferences().isHierarchicalDocumentSymbolSupported(); + boolean deprecatedSupported = preferenceManager.isClientSupportsDeprecated(); + DocumentSymbolHandler handler = new DocumentSymbolHandler(hierarchicalDocumentSymbolSupported, deprecatedSupported); waitForLifecycleJobs(monitor); return handler.documentSymbol(params, monitor); }); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java index f5360ad89c..8cec3a1a46 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java @@ -18,6 +18,7 @@ import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.IJavaSearchScope; @@ -57,17 +58,19 @@ public static List search(String query, int maxResults, Strin if (query.contains("*") || query.contains("?")) { typeMatchRule |= SearchPattern.R_PATTERN_MATCH; } + final boolean deprecatedSupported = JavaLanguageServerPlugin.getPreferencesManager().isClientSupportsDeprecated(); new SearchEngine().searchAllTypeNames(null, SearchPattern.R_PATTERN_MATCH, query.trim().toCharArray(), typeMatchRule, IJavaSearchConstants.TYPE, searchScope, new TypeNameMatchRequestor() { @Override public void acceptTypeNameMatch(TypeNameMatch match) { try { Location location = null; + IType type = match.getType(); try { - if (!sourceOnly && match.getType().isBinary()) { - location = JDTUtils.toLocation(match.getType().getClassFile()); - } else if (!match.getType().isBinary()) { - location = JDTUtils.toLocation(match.getType()); + if (!sourceOnly && type.isBinary()) { + location = JDTUtils.toLocation(type.getClassFile()); + } else if (!type.isBinary()) { + location = JDTUtils.toLocation(type); } } catch (Exception e) { JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getSimpleTypeName(), e); @@ -80,6 +83,9 @@ public void acceptTypeNameMatch(TypeNameMatch match) { symbolInformation.setName(match.getSimpleTypeName()); symbolInformation.setKind(mapKind(match)); symbolInformation.setLocation(location); + if (deprecatedSupported) { + symbolInformation.setDeprecated(Flags.isDeprecated(match.getModifiers())); + } symbols.add(symbolInformation); if (maxResults > 0 && symbols.size() >= maxResults) { monitor.setCanceled(true); @@ -104,6 +110,7 @@ private SymbolKind mapKind(TypeNameMatch match) { } return SymbolKind.Class; } + }, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); } catch (Exception e) { if (e instanceof OperationCanceledException) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java index 6a2bc74348..ac45168138 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java @@ -274,4 +274,16 @@ public boolean isSupportedCodeActionKind(String kind) { .stream().filter(k -> kind.startsWith(k)).findAny().isPresent(); //@formatter:on } + + /** + * {@code true} if the client supports the deprecated property + */ + public boolean isDeprecatedSupported() { + //@formatter:off + return v3supported && capabilities.getTextDocument().getCompletion() != null + && capabilities.getTextDocument().getCompletion().getCompletionItem() != null + && capabilities.getTextDocument().getCompletion().getCompletionItem().getDeprecatedSupport() != null + && capabilities.getTextDocument().getCompletion().getCompletionItem().getDeprecatedSupport().booleanValue(); + //@formatter:on + } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java index 63b7ffef68..a3db3d9b4d 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java @@ -324,4 +324,10 @@ public boolean isClientSupportsCompletionDocumentationMarkDown() { return getClientPreferences() != null && getClientPreferences().isSupportsCompletionDocumentationMarkdown(); } + /** + * Checks whether the client supports deprecated flag + */ + public boolean isClientSupportsDeprecated() { + return getClientPreferences() != null && getClientPreferences().isDeprecatedSupported(); + } } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandlerTest.java index 6b49dde0bf..5fd0416ca4 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentSymbolHandlerTest.java @@ -168,7 +168,7 @@ private static List internalGetHierarchicalSymbols(IPr DocumentSymbolParams params = new DocumentSymbolParams(); params.setTextDocument(identifier); //@formatter:off - List symbols = new DocumentSymbolHandler(true) + List symbols = new DocumentSymbolHandler(true, true) .documentSymbol(params, monitor).stream() .map(Either::getRight).collect(toList()); //@formatter:on @@ -240,7 +240,7 @@ private List getSymbols(String className) DocumentSymbolParams params = new DocumentSymbolParams(); params.setTextDocument(identifier); //@formatter:off - List symbols = new DocumentSymbolHandler(false) + List symbols = new DocumentSymbolHandler(false, true) .documentSymbol(params, monitor).stream() .map(Either::getLeft).collect(toList()); //@formatter:on