diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java index 67863ebeb29..476228421dc 100644 --- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java +++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2020 IBM Corporation and others. + * Copyright (c) 2000, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -183,6 +183,7 @@ private FixMessages() { public static String StringBufferToStringBuilderFix_convert_msg; public static String StringConcatToTextBlockFix_convert_msg; public static String LambdaExpressionAndMethodRefFix_clean_up_expression_msg; + public static String InlineDeprecatedMethod_msg; static { // initialize resource bundle diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties index fa953c7dac4..d72caa32121 100644 --- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties +++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties @@ -162,6 +162,7 @@ ReturnExpressionFix_description=Remove variable assignment before return StringBufferToStringBuilderFix_convert_msg=Convert StringBuffer to StringBuilder StringConcatToTextBlockFix_convert_msg=Convert String concatenation to Text Block LambdaExpressionAndMethodRefFix_clean_up_expression_msg=Clean up lambda expression +InlineDeprecatedMethod_msg=Replace with inlined method OneIfRatherThanDuplicateBlocksThatFallThroughFix_description=Single 'if' statement rather than duplicate blocks that fall through PullOutIfFromIfElseFix_description=Pull out a duplicate 'if' from an if/else diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/InlineMethodFixCore.java b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/InlineMethodFixCore.java new file mode 100644 index 00000000000..57d67692ddb --- /dev/null +++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/InlineMethodFixCore.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.corext.fix; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; + +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.TextChange; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.manipulation.ICleanUpFixCore; +import org.eclipse.jdt.core.refactoring.CompilationUnitChange; + +import org.eclipse.jdt.internal.corext.refactoring.code.InlineMethodRefactoring; + +public class InlineMethodFixCore implements IProposableFix, ICleanUpFixCore { + + private final String fName; + private final ICompilationUnit fCompilationUnit; + private final InlineMethodRefactoring fRefactoring; + + private InlineMethodFixCore(String name, CompilationUnit compilationUnit, InlineMethodRefactoring refactoring) { + this.fName= name; + this.fCompilationUnit= (ICompilationUnit)compilationUnit.getJavaElement(); + this.fRefactoring= refactoring; + } + + public static InlineMethodFixCore create(String name, CompilationUnit compilationUnit, MethodInvocation methodInvocation) { + ICompilationUnit cu= (ICompilationUnit)compilationUnit.getJavaElement(); + InlineMethodRefactoring refactoring= InlineMethodRefactoring.create(cu, compilationUnit, + methodInvocation.getStartPosition(), methodInvocation.getLength()); + try { + RefactoringStatus status= refactoring.checkAllConditions(new NullProgressMonitor()); + if (!status.isOK()) { + return null; + } + } catch (OperationCanceledException | CoreException e) { + return null; + } + InlineMethodFixCore fix= new InlineMethodFixCore(name, compilationUnit, refactoring); + return fix; + } + @Override + public CompilationUnitChange createChange(IProgressMonitor progressMonitor) throws CoreException { + CompositeChange change= (CompositeChange)fRefactoring.createChange(progressMonitor); + CompilationUnitChange compilationUnitChange= new CompilationUnitChange(fName, fCompilationUnit); + Change[] changes= change.getChildren(); + if (changes.length == 1 && changes[0] instanceof TextChange textChange) { + compilationUnitChange.setEdit(textChange.getEdit()); + return compilationUnitChange; + } + return null; + } + + @Override + public String getDisplayString() { + return fName; + } + + @Override + public String getAdditionalProposalInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IStatus getStatus() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest1d8.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest1d8.java index 164bed6047b..0776f003c49 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest1d8.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest1d8.java @@ -6503,5 +6503,284 @@ public void testAssignInTryWithResources_04() throws Exception { assertExpectedExistInProposals(proposals, new String[] { expected }); } + @Test + public void testInlineDeprecated_1() throws Exception { + Hashtable options= JavaCore.getOptions(); + options.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, JavaCore.ENABLED); + JavaCore.setOptions(options); + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String src= + "package test1;\n" + + "\n" + + "class E {\n" + + " private class E1 {\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z;\n" + + " return foo(x, k);\n" + + " }\n" + + " }\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " return e1.foo(a, b, c);\n" + + " }\n" + + "}\n"; + ICompilationUnit cu= pack1.createCompilationUnit("E.java", src, false, null); + int offset= src.indexOf("e1.foo"); + AssistContext context= getCorrectionContext(cu, offset + 3, 3); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + + String expected= + "package test1;\n" + + "\n" + + "class E {\n" + + " private class E1 {\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z;\n" + + " return foo(x, k);\n" + + " }\n" + + " }\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " int k = 2*b + 3*c;\n" + + " return e1.foo(a, k);\n" + + " }\n" + + "}\n"; + assertExpectedExistInProposals(proposals, new String[] { expected }); + + } + + @Test + public void testInlineDeprecated_2() throws Exception { + Hashtable options= JavaCore.getOptions(); + options.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, JavaCore.ENABLED); + JavaCore.setOptions(options); + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String src= + "package test1;\n" + + "\n" + + "class E {\n" + + " private class E1 {\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z;\n" + + " return k;\n" + + " }\n" + + " }\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " return e1.foo(a, b, c);\n" + + " }\n" + + "}\n"; + ICompilationUnit cu= pack1.createCompilationUnit("E.java", src, false, null); + int offset= src.indexOf("e1.foo"); + AssistContext context= getCorrectionContext(cu, offset + 3, 3); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 0); + } + + @Test + public void testInlineDeprecated_3() throws Exception { + Hashtable options= JavaCore.getOptions(); + options.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, JavaCore.ENABLED); + JavaCore.setOptions(options); + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String src= + "package test1;\n" + + "\n" + + "class E {\n" + + " private class E1 {\n" + + " private int v = 5;\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z + v;\n" + + " return foo(x, k);\n" + + " }\n" + + " }\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " return e1.foo(a, b, c);\n" + + " }\n" + + "}\n"; + ICompilationUnit cu= pack1.createCompilationUnit("E.java", src, false, null); + int offset= src.indexOf("e1.foo"); + AssistContext context= getCorrectionContext(cu, offset + 3, 3); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + + String expected= + "package test1;\n" + + "\n" + + "class E {\n" + + " private class E1 {\n" + + " private int v = 5;\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z + v;\n" + + " return foo(x, k);\n" + + " }\n" + + " }\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " int k = 2*b + 3*c + e1.v;\n" + + " return e1.foo(a, k);\n" + + " }\n" + + "}\n"; + assertExpectedExistInProposals(proposals, new String[] { expected }); + } + + @Test + public void testInlineDeprecated_4() throws Exception { + Hashtable options= JavaCore.getOptions(); + options.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, JavaCore.ENABLED); + JavaCore.setOptions(options); + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String src= + "package test1;\n" + + "\n" + + "public class E1 {\n" + + " private int v = 5;\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z + v;\n" + + " return foo(x, k);\n" + + " }\n" + + "}\n"; + pack1.createCompilationUnit("E1.java", src, false, null); + String src1= + "package test1;\n" + + "\n" + + "class E {\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " return e1.foo(a, b, c);\n" + + " }\n" + + "}\n"; + ICompilationUnit cu1= pack1.createCompilationUnit("E.java", src1, false, null); + int offset= src1.indexOf("e1.foo"); + AssistContext context= getCorrectionContext(cu1, offset + 3, 3); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 0); + } + + @Test + public void testInlineDeprecated_5() throws Exception { + Hashtable options= JavaCore.getOptions(); + options.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, JavaCore.ENABLED); + JavaCore.setOptions(options); + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + String src= + "package test1;\n" + + "\n" + + "public class E1 {\n" + + " public int v = 5;\n" + + " public int foo(int a, int b) {\n" + + " return a + b;\n" + + " }\n" + + " /**\n" + + " * @deprecated use {@link #foo(int, int)} instead\n" + + " * @param x - x\n" + + " * @param y - y\n" + + " * @param z - z\n" + + " */\n" + + " @Deprecated\n" + + " public int foo(int x, int y, int z) {\n" + + " int k = 2*y + 3*z + v;\n" + + " return foo(x, k);\n" + + " }\n" + + "}\n"; + pack1.createCompilationUnit("E1.java", src, false, null); + String src1= + "package test1;\n" + + "\n" + + "class E {\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " return e1.foo(a, b, c);\n" + + " }\n" + + "}\n"; + ICompilationUnit cu1= pack1.createCompilationUnit("E.java", src1, false, null); + int offset= src1.indexOf("e1.foo"); + AssistContext context= getCorrectionContext(cu1, offset + 3, 3); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + + String expected= + "package test1;\n" + + "\n" + + "class E {\n" + + " public int callfoo(int a, int b, int c) {\n" + + " E1 e1= new E1();\n" + + " int k = 2*b + 3*c + e1.v;\n" + + " return e1.foo(a, k);\n" + + " }\n" + + "}\n"; + assertExpectedExistInProposals(proposals, new String[] { expected }); + } + } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java index ed83112c69b..1fda303f53d 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2022 IBM Corporation and others. + * Copyright (c) 2012, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -56,6 +56,7 @@ public interface IProposalRelevance { int CREATE_FIELD_PREFIX_OR_SUFFIX_MATCH= 9; int CREATE_OPTIONAL= 9; int CREATE_OPTIONAL_OF_NULLABLE= 9; + int INLINE_DEPRECATED_METHOD= 9; int ADD_ABSTRACT_MODIFIER= 8; int ADD_STATIC_MODIFIER= 8; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java index 848d304a4db..3fac8e14e92 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java @@ -54,6 +54,7 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -87,7 +88,9 @@ import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ForStatement; +import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.IDocElement; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; @@ -96,10 +99,12 @@ import org.eclipse.jdt.core.dom.InfixExpression; import org.eclipse.jdt.core.dom.Initializer; import org.eclipse.jdt.core.dom.InstanceofExpression; +import org.eclipse.jdt.core.dom.Javadoc; import org.eclipse.jdt.core.dom.LabeledStatement; import org.eclipse.jdt.core.dom.LambdaExpression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.MethodRef; import org.eclipse.jdt.core.dom.MethodReference; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; @@ -126,6 +131,8 @@ import org.eclipse.jdt.core.dom.SwitchExpression; import org.eclipse.jdt.core.dom.SwitchStatement; import org.eclipse.jdt.core.dom.SynchronizedStatement; +import org.eclipse.jdt.core.dom.TagElement; +import org.eclipse.jdt.core.dom.TextElement; import org.eclipse.jdt.core.dom.ThisExpression; import org.eclipse.jdt.core.dom.ThrowStatement; import org.eclipse.jdt.core.dom.TryStatement; @@ -166,7 +173,9 @@ import org.eclipse.jdt.internal.corext.fix.ControlStatementsFix; import org.eclipse.jdt.internal.corext.fix.ConvertLoopFixCore; import org.eclipse.jdt.internal.corext.fix.DoWhileRatherThanWhileFixCore; +import org.eclipse.jdt.internal.corext.fix.FixMessages; import org.eclipse.jdt.internal.corext.fix.IProposableFix; +import org.eclipse.jdt.internal.corext.fix.InlineMethodFixCore; import org.eclipse.jdt.internal.corext.fix.JoinVariableFixCore; import org.eclipse.jdt.internal.corext.fix.LambdaExpressionsFixCore; import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel; @@ -183,6 +192,7 @@ import org.eclipse.jdt.internal.corext.refactoring.code.ExtractTempRefactoring; import org.eclipse.jdt.internal.corext.refactoring.code.InlineTempRefactoring; import org.eclipse.jdt.internal.corext.refactoring.code.PromoteTempToFieldRefactoring; +import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; import org.eclipse.jdt.internal.corext.refactoring.structure.ImportRemover; import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesAnalyzer; import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesRefactoringCore; @@ -336,7 +346,8 @@ public boolean hasAssists(IInvocationContext context) throws CoreException { || getDoWhileRatherThanWhileProposal(context, coveringNode, null) || getStringConcatToTextBlockProposal(context, coveringNode, null) || getAddStaticMemberFavoritesProposals(coveringNode, null) - || getSplitSwitchLabelProposal(context, coveringNode, null); + || getSplitSwitchLabelProposal(context, coveringNode, null) + || getDeprecatedProposal(context, coveringNode, null); } return false; } @@ -410,6 +421,7 @@ public IJavaCompletionProposal[] getAssists(IInvocationContext context, IProblem getConvertToSwitchExpressionProposals(context, coveringNode, resultingCollections); getDoWhileRatherThanWhileProposal(context, coveringNode, resultingCollections); getStringConcatToTextBlockProposal(context, coveringNode, resultingCollections); + getDeprecatedProposal(context, coveringNode, resultingCollections); } return resultingCollections.toArray(new IJavaCompletionProposal[resultingCollections.size()]); } @@ -610,6 +622,138 @@ protected void init(Refactoring refactoring) throws CoreException { return false; } + private static CompilationUnit findCUForMethod(CompilationUnit compilationUnit, ICompilationUnit cu, IMethodBinding methodBinding) { + ASTNode methodDecl= compilationUnit.findDeclaringNode(methodBinding.getMethodDeclaration()); + if (methodDecl == null) { + // is methodDecl defined in another CU? + ITypeBinding declaringTypeDecl= methodBinding.getDeclaringClass().getTypeDeclaration(); + if (declaringTypeDecl.isFromSource()) { + ICompilationUnit targetCU= null; + try { + targetCU= ASTResolving.findCompilationUnitForBinding(cu, compilationUnit, declaringTypeDecl); + } catch (JavaModelException e) { /* can't do better */ + } + if (targetCU != null) { + return ASTResolving.createQuickFixAST(targetCU, null); + } + } + return null; + } + return compilationUnit; + } + + @SuppressWarnings("unused") + private static boolean getDeprecatedProposal(IInvocationContext context, ASTNode node, Collection proposals) { + if (!(node instanceof MethodInvocation)) { + node= node.getParent(); + if (!(node instanceof MethodInvocation)) { + return false; + } + } + MethodInvocation methodInvocation= (MethodInvocation) node; + IMethodBinding methodBinding= methodInvocation.resolveMethodBinding(); + if (methodBinding == null) { + return false; + } + IMethod method= (IMethod)methodBinding.getJavaElement(); + if (method == null) { + return false; + } + IAnnotationBinding[] annotations= methodBinding.getAnnotations(); + for (IAnnotationBinding annotation : annotations) { + if (annotation.getAnnotationType().getQualifiedName().equals("java.lang.Deprecated")) { //$NON-NLS-1$ + CompilationUnit sourceCu= (CompilationUnit)node.getRoot(); + CompilationUnit cu= findCUForMethod(sourceCu, (ICompilationUnit)sourceCu.getJavaElement(), methodBinding); + if (cu == null) { + return false; + } + try { + MethodDeclaration methodDeclaration= ASTNodeSearchUtil.getMethodDeclarationNode(method, cu); + Javadoc javadoc= methodDeclaration.getJavadoc(); + List tags= javadoc.tags(); + for (TagElement tag : tags) { + if (tag.getTagName().equals("@deprecated")) { //$NON-NLS-1$ + List fragments= tag.fragments(); + if (fragments.size() < 2) { + return false; + } + if (fragments.get(0) instanceof TextElement textElement) { + String text= textElement.getText().toLowerCase().trim(); + if (text.endsWith("use") || text.endsWith("replace by")) { //$NON-NLS-1$ //$NON-NLS-2$ + if (fragments.get(1) instanceof TagElement tagElement) { + if (tagElement.getTagName().equals("@link")) { //$NON-NLS-1$ + List linkFragments= tagElement.fragments(); + if (linkFragments.size() == 1) { + IDocElement linkFragment= linkFragments.get(0); + if (linkFragment instanceof MethodRef methodRef) { + IMethodBinding refBinding= (IMethodBinding) methodRef.resolveBinding(); + if (refBinding != null) { + class FindNewMethodVisitor extends ASTVisitor { + private boolean useMethodIsUsed= false; + private boolean referencesPrivate= false; + @Override + public boolean visit(MethodInvocation invocation) { + IMethodBinding binding= invocation.resolveMethodBinding(); + if (binding != null) { + if (binding.isEqualTo(refBinding)) { + useMethodIsUsed= true; + } + } + return false; + } + @Override + public boolean visit(SimpleName name) { + IBinding binding= name.resolveBinding(); + if (binding instanceof IVariableBinding varBinding + && varBinding.isField()) { + int modifiers= varBinding.getModifiers(); + if (Modifier.isPrivate(modifiers)) { + referencesPrivate= true; + } + } + return false; + } + public boolean isUseMethodUsed() { + return useMethodIsUsed; + } + public boolean referencesPrivateField() { + return referencesPrivate; + } + } + FindNewMethodVisitor findNewMethodVisitor= new FindNewMethodVisitor(); + methodDeclaration.accept(findNewMethodVisitor); + if (!findNewMethodVisitor.isUseMethodUsed()) { + return false; + } + if (findNewMethodVisitor.referencesPrivateField()) { + if (methodInvocation.getRoot() != methodDeclaration.getRoot()) { + return false; + } + } + if (proposals != null) { + IProposableFix fix= InlineMethodFixCore.create(FixMessages.InlineDeprecatedMethod_msg, (CompilationUnit)methodInvocation.getRoot(), methodInvocation); + if (fix != null) { + Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); + proposals.add(new FixCorrectionProposal(fix, null, IProposalRelevance.INLINE_DEPRECATED_METHOD, image, context)); + } + } + return true; + } + } + } + } + } + } + } + } + } + } catch (JavaModelException e) { + // ignore + } + } + } + return false; + } private static boolean getConvertAnonymousToNestedProposal(IInvocationContext context, final ASTNode node, Collection proposals) throws CoreException { if (!(node instanceof Name))