blob: 950cb77b1d26968be05b497cf72a62fc76305b05 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Renaud Waldura <renaud+eclipse@waldura.com> - Access to static proposal
* Benjamin Muskalla <bmuskalla@innoopract.com> - [quick fix] Shouldn't offer "Add throws declaration" quickfix for overriding signature if result would conflict with overridden signature
* Lukas Hanke <hanke@yatta.de> - Bug 241696 [quick fix] quickfix to iterate over a collection - https://bugs.eclipse.org/bugs/show_bug.cgi?id=241696
* Sandra Lions <sandra.lions-piron@oracle.com> - [quick fix] for qualified enum constants in switch-case labels - https://bugs.eclipse.org/bugs/90140
* Stephan Herrmann - Contribution for Bug 463360 - [override method][null] generating method override should not create redundant null annotations
* Microsoft Corporation - read preferences from the compilation unit
*******************************************************************************/
package org.eclipse.jdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.swt.graphics.Image;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.resources.IFile;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.EmptyStatement;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
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.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.IfStatement;
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.LambdaExpression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodReference;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NameQualifiedType;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.ProvidesDirective;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchExpression;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.UnionType;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.dom.NecessaryParenthesesChecker;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite;
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.dom.Selection;
import org.eclipse.jdt.internal.corext.dom.TypeRules;
import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
import org.eclipse.jdt.internal.corext.fix.CodeStyleFix;
import org.eclipse.jdt.internal.corext.fix.IProposableFix;
import org.eclipse.jdt.internal.corext.fix.Java50Fix;
import org.eclipse.jdt.internal.corext.fix.StringFix;
import org.eclipse.jdt.internal.corext.fix.TypeParametersFix;
import org.eclipse.jdt.internal.corext.fix.UnimplementedCodeFix;
import org.eclipse.jdt.internal.corext.fix.UnusedCodeFix;
import org.eclipse.jdt.internal.corext.refactoring.code.Invocations;
import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.refactoring.surround.ExceptionAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryCatchAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryCatchRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.util.NoCommentSourceRangeComputer;
import org.eclipse.jdt.internal.corext.refactoring.util.SurroundWithAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.JavaElementImageDescriptor;
import org.eclipse.jdt.ui.actions.GenerateHashCodeEqualsAction;
import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
import org.eclipse.jdt.ui.actions.InferTypeArgumentsAction;
import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
import org.eclipse.jdt.ui.cleanup.ICleanUp;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposal;
import org.eclipse.jdt.ui.text.java.correction.CUCorrectionProposal;
import org.eclipse.jdt.ui.text.java.correction.ChangeCorrectionProposal;
import org.eclipse.jdt.ui.text.java.correction.ICommandAccess;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.fix.CodeStyleCleanUp;
import org.eclipse.jdt.internal.ui.fix.Java50CleanUp;
import org.eclipse.jdt.internal.ui.fix.StringCleanUp;
import org.eclipse.jdt.internal.ui.fix.TypeParametersCleanUp;
import org.eclipse.jdt.internal.ui.fix.UnimplementedCodeCleanUp;
import org.eclipse.jdt.internal.ui.fix.UnnecessaryCodeCleanUp;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.jdt.internal.ui.refactoring.nls.ExternalizeWizard;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposal.ChangeDescription;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposal.InsertDescription;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposal.RemoveDescription;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ConstructorFromSuperclassProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.CreateNewObjectProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.CreateObjectReferenceProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.CreateVariableReferenceProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.MissingAnnotationAttributesProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ModifierChangeCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewMethodCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewProviderMethodDeclaration;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewVariableCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.RefactoringCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ReplaceCorrectionProposal;
import org.eclipse.jdt.internal.ui.util.ASTHelper;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
/**
*/
public class LocalCorrectionsSubProcessor {
private static final String RAW_TYPE_REFERENCE_ID= "org.eclipse.jdt.ui.correction.rawTypeReference"; //$NON-NLS-1$
private static final String ADD_EXCEPTION_TO_THROWS_ID= "org.eclipse.jdt.ui.correction.addThrowsDecl"; //$NON-NLS-1$
private static final String ADD_NON_NLS_ID= "org.eclipse.jdt.ui.correction.addNonNLS"; //$NON-NLS-1$
private static final String ADD_FIELD_QUALIFICATION_ID= "org.eclipse.jdt.ui.correction.qualifyField"; //$NON-NLS-1$
private static final String ADD_STATIC_ACCESS_ID= "org.eclipse.jdt.ui.correction.changeToStatic"; //$NON-NLS-1$
private static final String REMOVE_UNNECESSARY_NLS_TAG_ID= "org.eclipse.jdt.ui.correction.removeNlsTag"; //$NON-NLS-1$
public static void addUncaughtExceptionProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ICompilationUnit cu= context.getCompilationUnit();
CompilationUnit astRoot= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
while (selectedNode != null && !(selectedNode instanceof Statement) && !(selectedNode instanceof VariableDeclarationExpression)
&& (selectedNode.getLocationInParent() != LambdaExpression.BODY_PROPERTY) && !(selectedNode instanceof MethodReference)) {
selectedNode= selectedNode.getParent();
}
if (selectedNode == null) {
return;
}
boolean isSelectedNodeThrowStatement= false;
if (selectedNode instanceof ThrowStatement) {
isSelectedNodeThrowStatement= true;
}
int offset= selectedNode.getStartPosition();
int length= selectedNode.getLength();
int selectionEnd= context.getSelectionOffset() + context.getSelectionLength();
if (selectionEnd > offset + length) {
// extend the selection if more than one statement is selected (bug 72149)
length= selectionEnd - offset;
}
//Surround with proposals
SurroundWithTryCatchRefactoring refactoring= SurroundWithTryCatchRefactoring.create(cu, offset, length);
if (refactoring == null)
return;
List<String> affectedLocals= new ArrayList<>();
SimpleName vName= null;
ITypeBinding vType= null;
if (selectedNode.getAST().apiLevel() >= ASTHelper.JLS10 && (selectedNode instanceof VariableDeclarationStatement)) {
for (Object o : ((VariableDeclarationStatement) selectedNode).fragments()) {
VariableDeclarationFragment v= ((VariableDeclarationFragment) o);
vName= v.getName();
vType= ((VariableDeclarationStatement) selectedNode).getType().resolveBinding();
}
// If no references to 'var' type exist, entire statement will be placed in try block
SurroundWithTryCatchAnalyzer analyzer= new SurroundWithTryCatchAnalyzer(cu, Selection.createFromStartLength(offset, length));
astRoot.accept(analyzer);
affectedLocals= Arrays.asList(analyzer.getAffectedLocals()).stream().map(f -> f.getName().getIdentifier()).collect(Collectors.toList());
}
refactoring.setLeaveDirty(true);
if (refactoring.checkActivationBasics(astRoot).isOK() && !isSelectedNodeThrowStatement) {
String label;
if ((vType != null) && (vName != null) && ASTNodes.isVarType(selectedNode, astRoot) && affectedLocals.contains(vName.getIdentifier())) {
label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_surroundwith_trycatch_var_description, new Object[] { vName.getIdentifier(), vType.getName() });
} else {
label= CorrectionMessages.LocalCorrectionsSubProcessor_surroundwith_trycatch_description;
}
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, refactoring, IProposalRelevance.SURROUND_WITH_TRY_CATCH, image);
proposal.setLinkedProposalModel(refactoring.getLinkedProposalModel());
proposals.add(proposal);
}
if (JavaModelUtil.is1d7OrHigher(cu.getJavaProject())) {
refactoring= SurroundWithTryCatchRefactoring.create(cu, offset, length, true);
if (refactoring == null)
return;
refactoring.setLeaveDirty(true);
if (refactoring.checkActivationBasics(astRoot).isOK()) {
String label;
if ((vType != null) && (vName != null) && ASTNodes.isVarType(selectedNode, astRoot) && affectedLocals.contains(vName.getIdentifier())) {
label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_surroundwith_trymulticatch_var_description, new Object[] { vName.getIdentifier(), vType.getName() });
} else {
label= CorrectionMessages.LocalCorrectionsSubProcessor_surroundwith_trymulticatch_description;
}
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, refactoring, IProposalRelevance.SURROUND_WITH_TRY_MULTICATCH, image);
proposal.setLinkedProposalModel(refactoring.getLinkedProposalModel());
proposals.add(proposal);
}
}
//Catch exception
BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode);
if (decl == null) {
return;
}
ASTNode enclosingNode= SurroundWithAnalyzer.getEnclosingNode(selectedNode);
if (enclosingNode == null) {
return;
}
ITypeBinding[] uncaughtExceptions= ExceptionAnalyzer.perform(enclosingNode, Selection.createFromStartLength(offset, length));
if (uncaughtExceptions.length == 0) {
return;
}
TryStatement surroundingTry= ASTResolving.findParentTryStatement(selectedNode);
AST ast= astRoot.getAST();
if (surroundingTry != null && (ASTNodes.isParent(selectedNode, surroundingTry.getBody()) || selectedNode.getLocationInParent() == TryStatement.RESOURCES2_PROPERTY)) {
addAdditionalCatchProposal(context, proposals, cu, selectedNode, offset, length, decl, uncaughtExceptions, surroundingTry, ast);
if (JavaModelUtil.is1d7OrHigher(cu.getJavaProject())) {
List<CatchClause> catchClauses= surroundingTry.catchClauses();
List<ITypeBinding> filteredExceptions= SurroundWithTryCatchRefactoring.filterSubtypeExceptions(uncaughtExceptions);
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
ASTRewrite rewrite= ASTRewrite.create(ast);
if (catchClauses != null && catchClauses.size() == 1) {
String label= filteredExceptions.size() > 1
? CorrectionMessages.LocalCorrectionsSubProcessor_addexceptionstoexistingcatch_description
: CorrectionMessages.LocalCorrectionsSubProcessor_addexceptiontoexistingcatch_description;
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.ADD_EXCEPTIONS_TO_EXISTING_CATCH, image);
ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(decl, imports);
CatchClause catchClause= catchClauses.get(0);
Type originalType= catchClause.getException().getType();
if (originalType instanceof UnionType) {
UnionType unionType= (UnionType) originalType;
ListRewrite listRewrite= rewrite.getListRewrite(unionType, UnionType.TYPES_PROPERTY);
@SuppressWarnings("unchecked")
List<Type> existingTypes= new ArrayList<>(unionType.types());
for (int i= 0; i < filteredExceptions.size(); i++) {
Type addedType= addNewException(ast, filteredExceptions, rewrite, proposal, imports, importRewriteContext, i);
boolean isReplaced= false;
for (Type existingType : existingTypes) {
if (existingType.resolveBinding().isSubTypeCompatible(filteredExceptions.get(i))) {
listRewrite.replace(existingType, addedType, null);
isReplaced= true;
break;
}
}
if (!isReplaced) {
listRewrite.insertLast(addedType, null);
}
}
} else {
Type firstType= null;
List<Type> typesToAdd= new ArrayList<>();
for (int i= 0; i < filteredExceptions.size(); i++) {
Type addedType= addNewException(ast, filteredExceptions, rewrite, proposal, imports, importRewriteContext, i);
if (originalType.resolveBinding().isSubTypeCompatible(filteredExceptions.get(i))) {
firstType= addedType;
} else {
typesToAdd.add(addedType);
}
}
if (!typesToAdd.isEmpty()) {
UnionType newUnionType= ast.newUnionType();
List<Type> types= newUnionType.types();
if (firstType == null) {
types.add(ASTNodes.createMoveTarget(rewrite, originalType));
} else {
types.add(firstType);
}
types.addAll(typesToAdd);
rewrite.replace(originalType, newUnionType, null);
} else if (firstType != null) {
rewrite.replace(originalType, firstType, null);
}
}
proposals.add(proposal);
} else if (catchClauses != null && catchClauses.isEmpty() && filteredExceptions.size() > 1) {
String label= CorrectionMessages.LocalCorrectionsSubProcessor_addadditionalmulticatch_description;
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.ADD_EXCEPTIONS_TO_EXISTING_CATCH, image);
ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(decl, imports);
CodeScopeBuilder.Scope scope= CodeScopeBuilder.perform(decl, Selection.createFromStartLength(offset, length)).findScope(offset, length);
scope.setCursor(offset);
CatchClause newCatchClause= ast.newCatchClause();
String varName= StubUtility.getExceptionVariableName(cu.getJavaProject());
String name= scope.createName(varName, false);
SingleVariableDeclaration var= ast.newSingleVariableDeclaration();
var.setName(ast.newSimpleName(name));
UnionType newUnionType= ast.newUnionType();
List<Type> types= newUnionType.types();
for (int i= 0; i < filteredExceptions.size(); i++) {
types.add(addNewException(ast, filteredExceptions, rewrite, proposal, imports, importRewriteContext, i));
}
String nameKey= "name"; //$NON-NLS-1$
proposal.addLinkedPosition(rewrite.track(var.getName()), false, nameKey);
var.setType(newUnionType);
newCatchClause.setException(var);
String catchBody= StubUtility.getCatchBodyContent(cu, "Exception", name, selectedNode, String.valueOf('\n')); //$NON-NLS-1$
if (catchBody != null) {
ASTNode node= rewrite.createStringPlaceholder(catchBody, ASTNode.RETURN_STATEMENT);
newCatchClause.getBody().statements().add(node);
}
ListRewrite listRewrite= rewrite.getListRewrite(surroundingTry, TryStatement.CATCH_CLAUSES_PROPERTY);
listRewrite.insertFirst(newCatchClause, null);
proposals.add(proposal);
}
}
}
//Add throws declaration
if (enclosingNode instanceof MethodDeclaration) {
MethodDeclaration methodDecl= (MethodDeclaration) enclosingNode;
IMethodBinding binding= methodDecl.resolveBinding();
boolean isApplicable= binding != null;
if (isApplicable) {
IMethodBinding overriddenMethod= Bindings.findOverriddenMethod(binding, true);
if (overriddenMethod != null) {
isApplicable= overriddenMethod.getDeclaringClass().isFromSource();
if (!isApplicable) { // bug 349051
ITypeBinding[] exceptionTypes= overriddenMethod.getExceptionTypes();
ArrayList<ITypeBinding> unhandledExceptions= new ArrayList<>(uncaughtExceptions.length);
for (ITypeBinding curr : uncaughtExceptions) {
if (isSubtype(curr, exceptionTypes)) {
unhandledExceptions.add(curr);
}
}
uncaughtExceptions= unhandledExceptions.toArray(new ITypeBinding[unhandledExceptions.size()]);
isApplicable= uncaughtExceptions.length > 0;
}
}
if (isApplicable) {
ITypeBinding[] methodExceptions= binding.getExceptionTypes();
ArrayList<ITypeBinding> unhandledExceptions= new ArrayList<>(uncaughtExceptions.length);
for (ITypeBinding curr : uncaughtExceptions) {
if (!isSubtype(curr, methodExceptions)) {
unhandledExceptions.add(curr);
}
}
uncaughtExceptions= unhandledExceptions.toArray(new ITypeBinding[unhandledExceptions.size()]);
List<Type> exceptions= methodDecl.thrownExceptionTypes();
int nExistingExceptions= exceptions.size();
ChangeDescription[] desc= new ChangeDescription[nExistingExceptions + uncaughtExceptions.length];
for (int i= 0; i < exceptions.size(); i++) {
Type elem= exceptions.get(i);
if (isSubtype(elem.resolveBinding(), uncaughtExceptions)) {
desc[i]= new RemoveDescription();
}
}
for (int i= 0; i < uncaughtExceptions.length; i++) {
desc[i + nExistingExceptions]= new InsertDescription(uncaughtExceptions[i], ""); //$NON-NLS-1$
}
String label= CorrectionMessages.LocalCorrectionsSubProcessor_addthrows_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
ChangeMethodSignatureProposal proposal= new ChangeMethodSignatureProposal(label, cu, astRoot, binding, null, desc, IProposalRelevance.ADD_THROWS_DECLARATION, image);
for (int i= 0; i < uncaughtExceptions.length; i++) {
addExceptionTypeLinkProposals(proposal, uncaughtExceptions[i], proposal.getExceptionTypeGroupId(i + nExistingExceptions));
}
proposal.setCommandId(ADD_EXCEPTION_TO_THROWS_ID);
proposals.add(proposal);
}
}
}
}
private static Type addNewException(AST ast, List<ITypeBinding> filteredExceptions, ASTRewrite rewrite, LinkedCorrectionProposal proposal, ImportRewrite imports,
ImportRewriteContext importRewriteContext, int i) {
ITypeBinding excBinding= filteredExceptions.get(i);
Type type= imports.addImport(excBinding, ast, importRewriteContext, TypeLocation.EXCEPTION);
String typeKey= "type" + i; //$NON-NLS-1$
proposal.addLinkedPosition(rewrite.track(type), false, typeKey);
addExceptionTypeLinkProposals(proposal, excBinding, typeKey);
return type;
}
private static void addAdditionalCatchProposal(IInvocationContext context, Collection<ICommandAccess> proposals, ICompilationUnit cu, ASTNode selectedNode, int offset, int length,
BodyDeclaration decl,
ITypeBinding[] uncaughtExceptions, TryStatement surroundingTry, AST ast) throws CoreException {
ASTRewrite rewrite= ASTRewrite.create(surroundingTry.getAST());
String label= CorrectionMessages.LocalCorrectionsSubProcessor_addadditionalcatch_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.ADD_ADDITIONAL_CATCH, image);
ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(decl, imports);
CodeScopeBuilder.Scope scope= CodeScopeBuilder.perform(decl, Selection.createFromStartLength(offset, length)).findScope(offset, length);
scope.setCursor(offset);
ListRewrite clausesRewrite= rewrite.getListRewrite(surroundingTry, TryStatement.CATCH_CLAUSES_PROPERTY);
for (int i= 0; i < uncaughtExceptions.length; i++) {
ITypeBinding excBinding= uncaughtExceptions[i];
String varName= StubUtility.getExceptionVariableName(cu.getJavaProject());
String name= scope.createName(varName, false);
SingleVariableDeclaration var= ast.newSingleVariableDeclaration();
var.setName(ast.newSimpleName(name));
var.setType(imports.addImport(excBinding, ast, importRewriteContext, TypeLocation.EXCEPTION));
CatchClause newClause= ast.newCatchClause();
newClause.setException(var);
String catchBody= StubUtility.getCatchBodyContent(cu, excBinding.getName(), name, selectedNode, String.valueOf('\n'));
if (catchBody != null) {
ASTNode node= rewrite.createStringPlaceholder(catchBody, ASTNode.RETURN_STATEMENT);
newClause.getBody().statements().add(node);
}
clausesRewrite.insertLast(newClause, null);
String typeKey= "type" + i; //$NON-NLS-1$
String nameKey= "name" + i; //$NON-NLS-1$
proposal.addLinkedPosition(rewrite.track(var.getType()), false, typeKey);
proposal.addLinkedPosition(rewrite.track(var.getName()), false, nameKey);
addExceptionTypeLinkProposals(proposal, excBinding, typeKey);
}
proposals.add(proposal);
}
private static void addExceptionTypeLinkProposals(LinkedCorrectionProposal proposal, ITypeBinding exc, String key) {
// all super classes except Object
while (exc != null && !"java.lang.Object".equals(exc.getQualifiedName())) { //$NON-NLS-1$
proposal.addLinkedPositionProposal(key, exc);
exc= exc.getSuperclass();
}
}
private static boolean isSubtype(ITypeBinding curr, ITypeBinding[] addedExceptions) {
while (curr != null) {
for (ITypeBinding addedException : addedExceptions) {
if (curr == addedException) {
return true;
}
}
curr= curr.getSuperclass();
}
return false;
}
public static void addUnreachableCatchProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
QuickAssistProcessor.getCatchClauseToThrowsProposals(context, selectedNode, proposals);
}
public static void addNLSProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
final ICompilationUnit cu= context.getCompilationUnit();
if (cu == null || !cu.exists()) {
return;
}
String name= CorrectionMessages.LocalCorrectionsSubProcessor_externalizestrings_description;
ChangeCorrectionProposal proposal= new ChangeCorrectionProposal(name, null, IProposalRelevance.EXTERNALIZE_STRINGS, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE)) {
@Override
public void apply(IDocument document) {
ExternalizeWizard.open(cu, JavaPlugin.getActiveWorkbenchShell());
}
@Override
public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
return CorrectionMessages.LocalCorrectionsSubProcessor_externalizestrings_additional_info;
}
};
proposals.add(proposal);
IProposableFix fix= StringFix.createFix(context.getASTRoot(), problem, false, true);
if (fix != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_NLS_NEVER_TRANSLATE);
Map<String, String> options= new Hashtable<>();
options.put(CleanUpConstants.ADD_MISSING_NLS_TAGS, CleanUpOptions.TRUE);
FixCorrectionProposal addNLS= new FixCorrectionProposal(fix, new StringCleanUp(options), IProposalRelevance.ADD_MISSING_NLS_TAGS, image, context);
addNLS.setCommandId(ADD_NON_NLS_ID);
proposals.add(addNLS);
}
}
public static void getUnnecessaryNLSTagProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
IProposableFix fix= StringFix.createFix(context.getASTRoot(), problem, true, false);
if (fix != null) {
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
Map<String, String> options= new Hashtable<>();
options.put(CleanUpConstants.REMOVE_UNNECESSARY_NLS_TAGS, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new StringCleanUp(options), IProposalRelevance.UNNECESSARY_NLS_TAG, image, context);
proposal.setCommandId(REMOVE_UNNECESSARY_NLS_TAG_ID);
proposals.add(proposal);
}
}
/*
* Fix instance accesses and indirect (static) accesses to static fields/methods
*/
public static void addCorrectAccessToStaticProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
IProposableFix fix= CodeStyleFix.createIndirectAccessToStaticFix(context.getASTRoot(), problem);
if (fix != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> options= new HashMap<>();
options.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS, CleanUpOptions.TRUE);
options.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new CodeStyleCleanUp(options), IProposalRelevance.CREATE_INDIRECT_ACCESS_TO_STATIC, image, context);
proposal.setCommandId(ADD_STATIC_ACCESS_ID);
proposals.add(proposal);
return;
}
IProposableFix[] fixes= CodeStyleFix.createNonStaticAccessFixes(context.getASTRoot(), problem);
if (fixes != null) {
IProposableFix fix1= fixes[0];
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> options= new HashMap<>();
options.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS, CleanUpOptions.TRUE);
options.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix1, new CodeStyleCleanUp(options), IProposalRelevance.CREATE_NON_STATIC_ACCESS_USING_DECLARING_TYPE, image, context);
proposal.setCommandId(ADD_STATIC_ACCESS_ID);
proposals.add(proposal);
if (fixes.length > 1) {
Map<String, String> options1= new HashMap<>();
options1.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS, CleanUpOptions.TRUE);
options1.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS, CleanUpOptions.TRUE);
options1.put(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS, CleanUpOptions.TRUE);
IProposableFix fix2= fixes[1];
proposal= new FixCorrectionProposal(fix2, new CodeStyleCleanUp(options1), IProposalRelevance.CREATE_NON_STATIC_ACCESS_USING_INSTANCE_TYPE, image, context);
proposals.add(proposal);
}
}
ModifierCorrectionSubProcessor.addNonAccessibleReferenceProposal(context, problem, proposals, ModifierCorrectionSubProcessor.TO_NON_STATIC, IProposalRelevance.REMOVE_STATIC_MODIFIER);
}
public static void addUnimplementedMethodsProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
IProposableFix addMethodFix= UnimplementedCodeFix.createAddUnimplementedMethodsFix(context.getASTRoot(), problem);
if (addMethodFix != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> settings= new Hashtable<>();
settings.put(CleanUpConstants.ADD_MISSING_METHODES, CleanUpOptions.TRUE);
ICleanUp cleanUp= new UnimplementedCodeCleanUp(settings);
proposals.add(new FixCorrectionProposal(addMethodFix, cleanUp, IProposalRelevance.ADD_UNIMPLEMENTED_METHODS, image, context));
}
IProposableFix makeAbstractFix= UnimplementedCodeFix.createMakeTypeAbstractFix(context.getASTRoot(), problem);
if (makeAbstractFix != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> settings= new Hashtable<>();
settings.put(UnimplementedCodeCleanUp.MAKE_TYPE_ABSTRACT, CleanUpOptions.TRUE);
ICleanUp cleanUp= new UnimplementedCodeCleanUp(settings);
proposals.add(new FixCorrectionProposal(makeAbstractFix, cleanUp, IProposalRelevance.MAKE_TYPE_ABSTRACT, image, context));
}
}
public static void addUninitializedLocalVariableProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ICompilationUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof Name)) {
return;
}
Name name= (Name) selectedNode;
IBinding binding= name.resolveBinding();
if (!(binding instanceof IVariableBinding)) {
return;
}
IVariableBinding varBinding= (IVariableBinding) binding;
CompilationUnit astRoot= context.getASTRoot();
ASTNode node= astRoot.findDeclaringNode(binding);
if (node instanceof VariableDeclarationFragment) {
ASTRewrite rewrite= ASTRewrite.create(node.getAST());
VariableDeclarationFragment fragment= (VariableDeclarationFragment) node;
if (fragment.getInitializer() != null) {
return;
}
Expression expression= ASTNodeFactory.newDefaultExpression(astRoot.getAST(), varBinding.getType());
if (expression == null) {
return;
}
rewrite.set(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY, expression, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_uninitializedvariable_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.INITIALIZE_VARIABLE, image);
proposal.addLinkedPosition(rewrite.track(expression), false, "initializer"); //$NON-NLS-1$
proposals.add(proposal);
}
}
public static void addConstructorFromSuperclassProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
TypeDeclaration typeDeclaration= null;
if (selectedNode.getLocationInParent() == TypeDeclaration.NAME_PROPERTY) {
typeDeclaration= (TypeDeclaration) selectedNode.getParent();
} else {
BodyDeclaration declaration= ASTResolving.findParentBodyDeclaration(selectedNode);
if (declaration instanceof Initializer && problem.getProblemId() == IProblem.UnhandledExceptionInDefaultConstructor) {
addUncaughtExceptionProposals(context, problem, proposals);
}
return;
}
ITypeBinding binding= typeDeclaration.resolveBinding();
if (binding == null || binding.getSuperclass() == null) {
return;
}
ICompilationUnit cu= context.getCompilationUnit();
for (IMethodBinding curr : binding.getSuperclass().getDeclaredMethods()) {
if (curr.isConstructor() && !Modifier.isPrivate(curr.getModifiers())) {
proposals.add(new ConstructorFromSuperclassProposal(cu, typeDeclaration, curr, IProposalRelevance.ADD_CONSTRUCTOR_FROM_SUPER_CLASS));
}
}
}
public static void addNewObjectProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
ASTNode selectedExpressionStatement= ASTNodes.getParent(selectedNode, ASTNode.EXPRESSION_STATEMENT);
if (selectedExpressionStatement != null) {
ExpressionStatement expressionStatement= (ExpressionStatement) selectedExpressionStatement;
Expression expression= expressionStatement.getExpression();
ITypeBinding binding= null;
if (expression instanceof MethodInvocation) {
Expression expression2= ((MethodInvocation) expression).getExpression();
binding= expression2 == null ? null : expression2.resolveTypeBinding();
}
if (binding == null) {
return;
}
ICompilationUnit cu= context.getCompilationUnit();
CreateNewObjectProposal createNewObjectProposal= new CreateNewObjectProposal(cu, expressionStatement, binding, IProposalRelevance.ADD_CONSTRUCTOR_FROM_SUPER_CLASS);
if (createNewObjectProposal.hasProposal()) {
proposals.add(createNewObjectProposal);
}
return;
}
ASTNode selectedVariableDeclarationFragment= ASTNodes.getParent(selectedNode, ASTNode.VARIABLE_DECLARATION_FRAGMENT);
if (selectedVariableDeclarationFragment != null) {
VariableDeclarationFragment vdf= (VariableDeclarationFragment) selectedVariableDeclarationFragment;
VariableDeclarationStatement vds= (VariableDeclarationStatement) ASTNodes.getParent(selectedNode, ASTNode.VARIABLE_DECLARATION_STATEMENT);
if (vds == null) {
return;
}
Type type= vds.getType();
ITypeBinding binding= null;
binding= type == null ? null : type.resolveBinding();
if (binding == null) {
return;
}
ICompilationUnit cu= context.getCompilationUnit();
CreateNewObjectProposal createNewObjectProposal= new CreateNewObjectProposal(cu, vdf, binding, IProposalRelevance.ADD_CONSTRUCTOR_FROM_SUPER_CLASS);
if (createNewObjectProposal.hasProposal()) {
proposals.add(createNewObjectProposal);
}
/* create instance of qualifier, ex; X in X.s; */
Expression initializer= vdf.getInitializer();
if(initializer instanceof QualifiedName == false) {
return;
}
QualifiedName qualifiedName= (QualifiedName)initializer;
IBinding resolveBinding= qualifiedName.getName().resolveBinding();
if(resolveBinding instanceof IVariableBinding == false) {
return;
}
CreateNewObjectProposal createNewObjectProposal2= new CreateNewObjectProposal(cu, vdf, (IVariableBinding)resolveBinding, IProposalRelevance.ADD_CONSTRUCTOR_FROM_SUPER_CLASS);
if (createNewObjectProposal2.hasProposal()) {
proposals.add(createNewObjectProposal2);
}
return;
}
if (problem.getProblemId() == IProblem.StaticMethodRequested ||
problem.getProblemId() == IProblem.NonStaticFieldFromStaticInvocation) {
addUncaughtExceptionProposals(context, problem, proposals);
}
}
public static void addObjectReferenceProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
ITypeBinding binding= null;
if (selectedNode == null) {
return;
}
if (problem.getProblemId() == IProblem.NonStaticFieldFromStaticInvocation) {
if (selectedNode instanceof QualifiedName) {
QualifiedName qualifiedName= (QualifiedName) selectedNode;
Name qualifier= qualifiedName.getQualifier();
binding= qualifier.resolveTypeBinding();
}
} else {
selectedNode= ASTNodes.getParent(selectedNode, ASTNode.EXPRESSION_STATEMENT);
if (selectedNode == null) {
if (problem.getProblemId() == IProblem.StaticMethodRequested) {
addUncaughtExceptionProposals(context, problem, proposals);
}
return;
}
ExpressionStatement expressionStatement= (ExpressionStatement) selectedNode;
Expression expression= expressionStatement.getExpression();
if (expression instanceof MethodInvocation) {
Expression expression2= ((MethodInvocation) expression).getExpression();
binding= expression2 == null ? null : expression2.resolveTypeBinding();
}
}
if (binding == null) {
return;
}
ICompilationUnit cu= context.getCompilationUnit();
CreateObjectReferenceProposal createObjectReferenceProposal= new CreateObjectReferenceProposal(cu, selectedNode, binding, IProposalRelevance.ADD_CONSTRUCTOR_FROM_SUPER_CLASS);
if (createObjectReferenceProposal.hasProposal()) {
proposals.add(createObjectReferenceProposal);
}
}
public static void addVariableReferenceProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
selectedNode= ASTNodes.getParent(selectedNode, ASTNode.VARIABLE_DECLARATION_FRAGMENT);
if (selectedNode == null) {
if (problem.getProblemId() == IProblem.NonStaticFieldFromStaticInvocation) {
addUncaughtExceptionProposals(context, problem, proposals);
}
return;
}
VariableDeclarationFragment fragment= (VariableDeclarationFragment) selectedNode;
Type type= null;
if(fragment.getParent() instanceof VariableDeclarationStatement) {
type= ((VariableDeclarationStatement)fragment.getParent()).getType();
} else if(fragment.getParent() instanceof FieldDeclaration) {
type= ((FieldDeclaration)fragment.getParent()).getType();
}
if (type == null) {
return;
}
ITypeBinding binding= type.resolveBinding();
if (binding == null) {
return;
}
ICompilationUnit cu= context.getCompilationUnit();
CreateVariableReferenceProposal createVariableReferenceProposal= new CreateVariableReferenceProposal(cu, fragment, binding, IProposalRelevance.ADD_CONSTRUCTOR_FROM_SUPER_CLASS);
if (createVariableReferenceProposal.hasProposal()) {
proposals.add(createVariableReferenceProposal);
}
}
public static void addUnusedMemberProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
int problemId= problem.getProblemId();
UnusedCodeFix fix= UnusedCodeFix.createUnusedMemberFix(context.getASTRoot(), problem, false);
if (fix != null) {
addProposal(context, proposals, fix);
}
if (problemId == IProblem.LocalVariableIsNeverUsed) {
fix= UnusedCodeFix.createUnusedMemberFix(context.getASTRoot(), problem, true);
addProposal(context, proposals, fix);
}
if (problemId == IProblem.ArgumentIsNeverUsed) {
JavadocTagsSubProcessor.getUnusedAndUndocumentedParameterOrExceptionProposals(context, problem, proposals);
}
if (problemId == IProblem.UnusedPrivateField) {
GetterSetterCorrectionSubProcessor.addGetterSetterProposal(context, problem, proposals, IProposalRelevance.GETTER_SETTER_UNUSED_PRIVATE_FIELD);
}
}
public static void addUnusedTypeParameterProposal(IInvocationContext context, IProblemLocation problemLoc, Collection<ICommandAccess> proposals) {
UnusedCodeFix fix= UnusedCodeFix.createUnusedTypeParameterFix(context.getASTRoot(), problemLoc);
if (fix != null) {
addProposal(context, proposals, fix);
}
JavadocTagsSubProcessor.getUnusedAndUndocumentedParameterOrExceptionProposals(context, problemLoc, proposals);
}
public static void addRedundantSuperInterfaceProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode instanceof Name)) {
return;
}
ASTNode node= ASTNodes.getNormalizedNode(selectedNode);
ASTRewrite rewrite= ASTRewrite.create(node.getAST());
rewrite.remove(node, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_remove_redundant_superinterface;
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REMOVE_REDUNDANT_SUPER_INTERFACE, image);
proposals.add(proposal);
}
private static void addProposal(IInvocationContext context, Collection<ICommandAccess> proposals, final UnusedCodeFix fix) {
if (fix != null) {
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, fix.getCleanUp(), IProposalRelevance.UNUSED_MEMBER, image, context);
proposals.add(proposal);
}
}
public static void addSuperfluousSemicolonProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
String label= CorrectionMessages.LocalCorrectionsSubProcessor_removesemicolon_description;
ReplaceCorrectionProposal proposal= new ReplaceCorrectionProposal(label, context.getCompilationUnit(), problem.getOffset(), problem.getLength(), "", IProposalRelevance.REMOVE_SEMICOLON); //$NON-NLS-1$
proposals.add(proposal);
}
public static void addUnnecessaryCastProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
IProposableFix fix= UnusedCodeFix.createRemoveUnusedCastFix(context.getASTRoot(), problem);
if (fix != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> options= new Hashtable<>();
options.put(CleanUpConstants.REMOVE_UNNECESSARY_CASTS, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new UnnecessaryCodeCleanUp(options), IProposalRelevance.REMOVE_UNUSED_CAST, image, context);
proposals.add(proposal);
}
}
public static void addUnnecessaryInstanceofProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
ASTNode curr= ASTNodes.getUnparenthesedExpression(selectedNode);
if (curr instanceof InstanceofExpression) {
AST ast= curr.getAST();
ASTRewrite rewrite= ASTRewrite.create(ast);
InstanceofExpression inst= (InstanceofExpression) curr;
InfixExpression expression= ast.newInfixExpression();
expression.setLeftOperand((Expression) rewrite.createCopyTarget(inst.getLeftOperand()));
expression.setOperator(InfixExpression.Operator.NOT_EQUALS);
expression.setRightOperand(ast.newNullLiteral());
rewrite.replace(inst, expression, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_unnecessaryinstanceof_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.UNNECESSARY_INSTANCEOF, image);
proposals.add(proposal);
}
}
public static void addIllegalQualifiedEnumConstantLabelProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode coveringNode= problem.getCoveringNode(context.getASTRoot());
ASTNode curr= ASTNodes.getUnparenthesedExpression(coveringNode);
if (!(curr instanceof QualifiedName)) {
return;
}
SimpleName simpleName= ((QualifiedName) curr).getName();
final ASTRewrite rewrite= ASTRewrite.create(curr.getAST());
rewrite.replace(coveringNode, simpleName, null);
String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_replace_with_unqualified_enum_constant, BasicElementLabels.getJavaElementName(simpleName.getIdentifier()));
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REPLACE_WITH_UNQUALIFIED_ENUM_CONSTANT, image);
proposals.add(proposal);
}
public static void addUnnecessaryThrownExceptionProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
selectedNode= ASTNodes.getNormalizedNode(selectedNode);
if (selectedNode == null || selectedNode.getLocationInParent() != MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY) {
return;
}
MethodDeclaration decl= (MethodDeclaration) selectedNode.getParent();
IMethodBinding binding= decl.resolveBinding();
if (binding != null) {
List<Type> thrownExceptions= decl.thrownExceptionTypes();
int index= thrownExceptions.indexOf(selectedNode);
if (index == -1) {
return;
}
ChangeDescription[] desc= new ChangeDescription[thrownExceptions.size()];
desc[index]= new RemoveDescription();
ICompilationUnit cu= context.getCompilationUnit();
String label= CorrectionMessages.LocalCorrectionsSubProcessor_unnecessarythrow_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
proposals.add(new ChangeMethodSignatureProposal(label, cu, selectedNode, binding, null, desc, IProposalRelevance.UNNECESSARY_THROW, image));
}
JavadocTagsSubProcessor.getUnusedAndUndocumentedParameterOrExceptionProposals(context, problem, proposals);
}
public static void addUnqualifiedFieldAccessProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
IProposableFix fix= CodeStyleFix.createAddFieldQualifierFix(context.getASTRoot(), problem);
if (fix != null) {
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> options= new HashMap<>();
options.put(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS, CleanUpOptions.TRUE);
options.put(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new CodeStyleCleanUp(options), IProposalRelevance.ADD_FIELD_QUALIFIER, image, context);
proposal.setCommandId(ADD_FIELD_QUALIFICATION_ID);
proposals.add(proposal);
}
}
public static void addInvalidVariableNameProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
// hiding, redefined or future keyword
CompilationUnit root= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(root);
if (selectedNode instanceof MethodDeclaration) {
selectedNode= ((MethodDeclaration) selectedNode).getName();
}
if (!(selectedNode instanceof SimpleName)) {
return;
}
SimpleName nameNode= (SimpleName) selectedNode;
String valueSuggestion= null;
String name;
switch (problem.getProblemId()) {
case IProblem.LocalVariableHidingLocalVariable:
case IProblem.LocalVariableHidingField:
name= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_hiding_local_label, BasicElementLabels.getJavaElementName(nameNode.getIdentifier()));
break;
case IProblem.FieldHidingLocalVariable:
case IProblem.FieldHidingField:
case IProblem.DuplicateField:
name= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_hiding_field_label, BasicElementLabels.getJavaElementName(nameNode.getIdentifier()));
break;
case IProblem.ArgumentHidingLocalVariable:
case IProblem.ArgumentHidingField:
name= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_hiding_argument_label, BasicElementLabels.getJavaElementName(nameNode.getIdentifier()));
break;
case IProblem.DuplicateMethod:
name= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_renaming_duplicate_method, BasicElementLabels.getJavaElementName(nameNode.getIdentifier()));
break;
default:
name= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_rename_var_label, BasicElementLabels.getJavaElementName(nameNode.getIdentifier()));
}
if (problem.getProblemId() == IProblem.UseEnumAsAnIdentifier) {
valueSuggestion= "enumeration"; //$NON-NLS-1$
} else {
valueSuggestion= nameNode.getIdentifier() + '1';
}
LinkedNamesAssistProposal proposal= new LinkedNamesAssistProposal(name, context, nameNode, valueSuggestion);
proposals.add(proposal);
}
public static void getInvalidOperatorProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit root= context.getASTRoot();
AST ast= root.getAST();
ASTNode selectedNode= ASTNodes.getUnparenthesedExpression(problem.getCoveringNode(root));
if (selectedNode instanceof PrefixExpression) {
// !x instanceof X -> !(x instanceof X)
PrefixExpression expression= (PrefixExpression) selectedNode;
if (expression.getOperator() == PrefixExpression.Operator.NOT) {
ASTNode parent= expression.getParent();
String label= null;
switch (parent.getNodeType()) {
case ASTNode.INSTANCEOF_EXPRESSION:
label= CorrectionMessages.LocalCorrectionsSubProcessor_setparenteses_instanceof_description;
break;
case ASTNode.INFIX_EXPRESSION:
InfixExpression infixExpression= (InfixExpression) parent;
label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_setparenteses_description, infixExpression.getOperator().toString());
break;
}
if (label != null) {
ASTRewrite rewrite= ASTRewrite.create(ast);
rewrite.replace(selectedNode, rewrite.createMoveTarget(expression.getOperand()), null);
ParenthesizedExpression newParentExpr= ast.newParenthesizedExpression();
newParentExpr.setExpression((Expression) rewrite.createMoveTarget(parent));
PrefixExpression newPrefixExpr= ast.newPrefixExpression();
newPrefixExpr.setOperand(newParentExpr);
newPrefixExpr.setOperator(PrefixExpression.Operator.NOT);
rewrite.replace(parent, newPrefixExpr, null);
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CAST);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.INVALID_OPERATOR, image);
proposals.add(proposal);
}
}
} else if (selectedNode instanceof InfixExpression && isBitOperation((((InfixExpression) selectedNode).getOperator()))) {
// a & b == c -> (a & b) == c
final CompareInBitWiseOpFinder opFinder= new CompareInBitWiseOpFinder(selectedNode);
if (opFinder.getCompareExpression() != null) { // compare operation inside bit operations: set parents
String label= CorrectionMessages.LocalCorrectionsSubProcessor_setparenteses_bitop_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CAST);
CUCorrectionProposal proposal= new CUCorrectionProposal(label, context.getCompilationUnit(), IProposalRelevance.INVALID_OPERATOR, image) {
@Override
protected void addEdits(IDocument document, TextEdit edit) throws CoreException {
InfixExpression compareExpression= opFinder.getCompareExpression();
InfixExpression expression= opFinder.getParentInfixExpression();
ASTNode left= compareExpression.getLeftOperand();
if (expression.getStartPosition() < left.getStartPosition()) {
edit.addChild(new InsertEdit(expression.getStartPosition(), String.valueOf('(')));
edit.addChild(new InsertEdit(ASTNodes.getExclusiveEnd(left), String.valueOf(')')));
}
ASTNode rigth= compareExpression.getRightOperand();
int selEnd= ASTNodes.getExclusiveEnd(expression);
if (selEnd > ASTNodes.getExclusiveEnd(rigth)) {
edit.addChild(new InsertEdit(rigth.getStartPosition(), String.valueOf('(')));
edit.addChild(new InsertEdit(selEnd, String.valueOf(')')));
}
}
};
proposals.add(proposal);
}
}
}
private static boolean isBitOperation(InfixExpression.Operator op) {
return op == InfixExpression.Operator.AND || op == InfixExpression.Operator.OR || op == InfixExpression.Operator.XOR;
}
private static class CompareInBitWiseOpFinder extends ASTVisitor {
private InfixExpression fCompareExpression= null;
private final ASTNode fSelectedNode;
public CompareInBitWiseOpFinder(ASTNode selectedNode) {
fSelectedNode= selectedNode;
selectedNode.accept(this);
}
@Override
public boolean visit(InfixExpression e) {
InfixExpression.Operator op= e.getOperator();
if (isBitOperation(op)) {
return true;
} else if (op == InfixExpression.Operator.EQUALS || op == InfixExpression.Operator.NOT_EQUALS) {
fCompareExpression= e;
return false;
}
return false;
}
public InfixExpression getCompareExpression() {
return fCompareExpression;
}
public InfixExpression getParentInfixExpression() {
ASTNode expr= fSelectedNode;
ASTNode parent= expr.getParent(); // include all parents
while (parent instanceof InfixExpression && isBitOperation(((InfixExpression) parent).getOperator())) {
expr= parent;
parent= expr.getParent();
}
return (InfixExpression) expr;
}
}
public static void getUnnecessaryElseProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit root= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(root);
if (selectedNode == null) {
return;
}
ASTNode parent= selectedNode.getParent();
if (parent instanceof ExpressionStatement) {
parent= parent.getParent();
}
if (!(parent instanceof IfStatement)) {
return;
}
IfStatement ifStatement= (IfStatement) parent;
ASTNode ifParent= ifStatement.getParent();
if (!(ifParent instanceof Block) && !(ifParent instanceof SwitchStatement) && !ASTNodes.isControlStatementBody(ifStatement.getLocationInParent())) {
return;
}
ASTRewrite rewrite= ASTRewrite.create(root.getAST());
ASTNode placeholder= QuickAssistProcessor.getCopyOfInner(rewrite, ifStatement.getElseStatement(), false);
if (placeholder == null) {
return;
}
rewrite.remove(ifStatement.getElseStatement(), null);
if (ifParent instanceof Block) {
ListRewrite listRewrite= rewrite.getListRewrite(ifParent, Block.STATEMENTS_PROPERTY);
listRewrite.insertAfter(placeholder, ifStatement, null);
} else if (ifParent instanceof SwitchStatement) {
ListRewrite listRewrite= rewrite.getListRewrite(ifParent, SwitchStatement.STATEMENTS_PROPERTY);
listRewrite.insertAfter(placeholder, ifStatement, null);
} else {
Block block= root.getAST().newBlock();
rewrite.replace(ifStatement, block, null);
block.statements().add(rewrite.createCopyTarget(ifStatement));
block.statements().add(placeholder);
}
String label= CorrectionMessages.LocalCorrectionsSubProcessor_removeelse_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REMOVE_ELSE, image);
proposals.add(proposal);
}
public static void getInterfaceExtendsClassProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit root= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(root);
if (selectedNode == null) {
return;
}
while (selectedNode.getParent() instanceof Type) {
selectedNode= selectedNode.getParent();
}
StructuralPropertyDescriptor locationInParent= selectedNode.getLocationInParent();
if (locationInParent != TypeDeclaration.SUPERCLASS_TYPE_PROPERTY) {
return;
}
TypeDeclaration typeDecl= (TypeDeclaration) selectedNode.getParent();
{
ASTRewrite rewrite= ASTRewrite.create(root.getAST());
ASTNode placeHolder= rewrite.createMoveTarget(selectedNode);
ListRewrite interfaces= rewrite.getListRewrite(typeDecl, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY);
interfaces.insertFirst(placeHolder, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_extendstoimplements_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CHANGE_EXTENDS_TO_IMPLEMENTS, image);
proposals.add(proposal);
}
{
ASTRewrite rewrite= ASTRewrite.create(root.getAST());
rewrite.set(typeDecl, TypeDeclaration.INTERFACE_PROPERTY, Boolean.TRUE, null);
String typeName= typeDecl.getName().getIdentifier();
String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_classtointerface_description, BasicElementLabels.getJavaElementName(typeName));
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CHANGE_CLASS_TO_INTERFACE, image);
proposals.add(proposal);
}
}
public static void addTypeAsPermittedSubTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws JavaModelException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
if (!ASTHelper.isSealedTypeSupportedInAST(selectedNode.getAST())) {
return;
}
while (selectedNode.getParent() instanceof Type) {
selectedNode= selectedNode.getParent();
}
if (selectedNode.getLocationInParent() != TypeDeclaration.SUPERCLASS_TYPE_PROPERTY
&& selectedNode.getLocationInParent() != TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY) {
return;
}
TypeDeclaration subType= (TypeDeclaration) selectedNode.getParent();
ITypeBinding subTypeBinding= subType.resolveBinding();
IJavaElement sealedTypeElement= null;
if (selectedNode instanceof SimpleType) {
ITypeBinding typeBinding= ((SimpleType) selectedNode).resolveBinding();
if (typeBinding != null) {
sealedTypeElement= typeBinding.getJavaElement();
}
}
if (!(sealedTypeElement instanceof IType)) {
return;
}
IType sealedType= (IType) sealedTypeElement;
if (sealedType.isBinary() || !sealedType.isSealed()) {
return;
}
ICompilationUnit compilationUnit= sealedType.getCompilationUnit();
CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(compilationUnit);
TypeDeclaration declaration= ASTNodeSearchUtil.getTypeDeclarationNode(sealedType, cuRewrite.getRoot());
if (declaration == null) {
return;
}
AST ast= declaration.getAST();
String subTypeName= subType.getName().getIdentifier();
Type type= ast.newSimpleType(ast.newSimpleName(subTypeName));
ASTRewrite astRewrite= cuRewrite.getASTRewrite();
astRewrite.getListRewrite(declaration, TypeDeclaration.PERMITS_TYPES_PROPERTY).insertLast(type, null);
String sealedTypeName= problem.getProblemArguments()[1];
String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_declareSubClassAsPermitsSealedClass_description, new String[] { subTypeName, sealedTypeName });
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, compilationUnit, astRewrite, IProposalRelevance.DECLARE_SEALED_AS_DIRECT_SUPER_TYPE, image);
ImportRewrite importRewrite= proposal.getImportRewrite();
if (importRewrite == null) {
importRewrite= StubUtility.createImportRewrite(compilationUnit, true);
}
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(declaration.getRoot(), importRewrite);
importRewrite.addImport(subTypeBinding, astRewrite.getAST(), importRewriteContext);
proposal.setImportRewrite(importRewrite);
proposals.add(proposal);
}
public static void addSealedAsDirectSuperTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws JavaModelException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
if (!ASTHelper.isSealedTypeSupportedInAST(selectedNode.getAST())) {
return;
}
while (selectedNode.getParent() instanceof Type) {
selectedNode= selectedNode.getParent();
}
if (selectedNode.getLocationInParent() != TypeDeclaration.PERMITS_TYPES_PROPERTY) {
return;
}
TypeDeclaration sealedType= (TypeDeclaration) selectedNode.getParent();
IJavaElement permittedTypeElement= null;
if (selectedNode instanceof SimpleType) {
ITypeBinding typeBinding= ((SimpleType) selectedNode).resolveBinding();
if (typeBinding != null) {
permittedTypeElement= typeBinding.getJavaElement();
}
}
if (!(permittedTypeElement instanceof IType)) {
return;
}
ICompilationUnit compilationUnit= ((IType) permittedTypeElement).getCompilationUnit();
if (compilationUnit == null) {
return;
}
CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(compilationUnit);
TypeDeclaration declaration= ASTNodeSearchUtil.getTypeDeclarationNode((IType) permittedTypeElement, cuRewrite.getRoot());
if (declaration == null) {
return;
}
AST ast= declaration.getAST();
String sealedTypeName= sealedType.getName().getIdentifier();
Type type= ast.newSimpleType(ast.newSimpleName(sealedTypeName));
ASTRewrite astRewrite= cuRewrite.getASTRewrite();
astRewrite.getListRewrite(declaration, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, null);
String permittedTypeName= problem.getProblemArguments()[0];
String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description, new String[] { sealedTypeName, permittedTypeName });
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, compilationUnit, astRewrite, IProposalRelevance.DECLARE_SEALED_AS_DIRECT_SUPER_TYPE, image);
ImportRewrite importRewrite= proposal.getImportRewrite();
if (importRewrite == null) {
importRewrite= StubUtility.createImportRewrite(compilationUnit, true);
}
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(declaration.getRoot(), importRewrite);
importRewrite.addImport(sealedType.resolveBinding(), astRewrite.getAST(), importRewriteContext);
proposal.setImportRewrite(importRewrite);
proposals.add(proposal);
}
public static void getUnreachableCodeProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit root= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(root);
if (selectedNode == null) {
return;
}
ASTNode parent= selectedNode.getParent();
while (parent instanceof ExpressionStatement) {
selectedNode= parent;
parent= selectedNode.getParent();
}
if (parent instanceof WhileStatement) {
addRemoveIncludingConditionProposal(context, parent, null, proposals);
} else if (selectedNode.getLocationInParent() == IfStatement.THEN_STATEMENT_PROPERTY) {
Statement elseStatement= ((IfStatement) parent).getElseStatement();
addRemoveIncludingConditionProposal(context, parent, elseStatement, proposals);
} else if (selectedNode.getLocationInParent() == IfStatement.ELSE_STATEMENT_PROPERTY) {
Statement thenStatement= ((IfStatement) parent).getThenStatement();
addRemoveIncludingConditionProposal(context, parent, thenStatement, proposals);
} else if (selectedNode.getLocationInParent() == ForStatement.BODY_PROPERTY) {
Statement body= ((ForStatement) parent).getBody();
addRemoveIncludingConditionProposal(context, parent, body, proposals);
} else if (selectedNode.getLocationInParent() == ConditionalExpression.THEN_EXPRESSION_PROPERTY) {
Expression elseExpression= ((ConditionalExpression) parent).getElseExpression();
addRemoveIncludingConditionProposal(context, parent, elseExpression, proposals);
} else if (selectedNode.getLocationInParent() == ConditionalExpression.ELSE_EXPRESSION_PROPERTY) {
Expression thenExpression= ((ConditionalExpression) parent).getThenExpression();
addRemoveIncludingConditionProposal(context, parent, thenExpression, proposals);
} else if (selectedNode.getLocationInParent() == InfixExpression.RIGHT_OPERAND_PROPERTY) {
// also offer split && / || condition proposals:
InfixExpression infixExpression= (InfixExpression) parent;
Expression leftOperand= infixExpression.getLeftOperand();
ASTRewrite rewrite= ASTRewrite.create(parent.getAST());
Expression replacement= ASTNodes.getUnparenthesedExpression(leftOperand);
Expression toReplace= infixExpression;
while (toReplace.getLocationInParent() == ParenthesizedExpression.EXPRESSION_PROPERTY) {
toReplace= (Expression) toReplace.getParent();
}
if (NecessaryParenthesesChecker.needsParentheses(replacement, toReplace.getParent(), toReplace.getLocationInParent())) {
if (leftOperand instanceof ParenthesizedExpression) {
replacement= (Expression) replacement.getParent();
} else if (infixExpression.getLocationInParent() == ParenthesizedExpression.EXPRESSION_PROPERTY) {
toReplace= ((ParenthesizedExpression) toReplace).getExpression();
}
}
rewrite.replace(toReplace, rewrite.createMoveTarget(replacement), null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_removeunreachablecode_description;
addRemoveProposal(context, rewrite, label, proposals);
AssistContext assistContext= new AssistContext(context.getCompilationUnit(), infixExpression.getRightOperand().getStartPosition() - 1, 0);
assistContext.setASTRoot(root);
AdvancedQuickAssistProcessor.getSplitAndConditionProposals(assistContext, infixExpression, proposals);
AdvancedQuickAssistProcessor.getSplitOrConditionProposals(assistContext, infixExpression, proposals);
} else if (selectedNode instanceof Statement && selectedNode.getLocationInParent().isChildListProperty()) {
// remove all statements following the unreachable:
List<Statement> statements= ASTNodes.<Statement>getChildListProperty(selectedNode.getParent(), (ChildListPropertyDescriptor) selectedNode.getLocationInParent());
int idx= statements.indexOf(selectedNode);
ASTRewrite rewrite= ASTRewrite.create(selectedNode.getAST());
String label= CorrectionMessages.LocalCorrectionsSubProcessor_removeunreachablecode_description;
if (idx > 0) {
Object prevStatement= statements.get(idx - 1);
if (prevStatement instanceof IfStatement) {
IfStatement ifStatement= (IfStatement) prevStatement;
if (ifStatement.getElseStatement() == null) {
// remove if (true), see https://bugs.eclipse.org/bugs/show_bug.cgi?id=261519
Statement thenStatement= ifStatement.getThenStatement();
label= CorrectionMessages.LocalCorrectionsSubProcessor_removeunreachablecode_including_condition_description;
if (thenStatement instanceof Block) {
// add all child nodes from Block node
List<Statement> thenStatements= ((Block) thenStatement).statements();
if (thenStatements.isEmpty()) {
return;
}
ASTNode[] thenStatementsArray= new ASTNode[thenStatements.size()];
for (int i= 0; i < thenStatementsArray.length; i++) {
thenStatementsArray[i]= thenStatements.get(i);
}
ASTNode newThenStatement= rewrite.createGroupNode(thenStatementsArray);
rewrite.replace(ifStatement, newThenStatement, null);
} else {
rewrite.replace(ifStatement, thenStatement, null);
}
}
}
}
for (int i= idx; i < statements.size(); i++) {
ASTNode statement= statements.get(i);
if (statement instanceof SwitchCase)
break; // stop at case *: and default:
rewrite.remove(statement, null);
}
addRemoveProposal(context, rewrite, label, proposals);
} else {
// no special case, just remove the node:
addRemoveProposal(context, selectedNode, proposals);
}
}
private static void addRemoveProposal(IInvocationContext context, ASTNode selectedNode, Collection<ICommandAccess> proposals) {
ASTRewrite rewrite= ASTRewrite.create(selectedNode.getAST());
rewrite.remove(selectedNode, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_removeunreachablecode_description;
addRemoveProposal(context, rewrite, label, proposals);
}
private static void addRemoveIncludingConditionProposal(IInvocationContext context, ASTNode toRemove, ASTNode replacement, Collection<ICommandAccess> proposals) {
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_removeunreachablecode_including_condition_description;
AST ast= toRemove.getAST();
ASTRewrite rewrite= ASTRewrite.create(ast);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REMOVE_UNREACHABLE_CODE_INCLUDING_CONDITION, image);
if (replacement == null
|| replacement instanceof EmptyStatement
|| replacement instanceof Block && ((Block) replacement).statements().size() == 0) {
if (ASTNodes.isControlStatementBody(toRemove.getLocationInParent())) {
rewrite.replace(toRemove, toRemove.getAST().newBlock(), null);
} else {
rewrite.remove(toRemove, null);
}
} else if (toRemove instanceof Expression && replacement instanceof Expression) {
Expression moved= (Expression) rewrite.createMoveTarget(replacement);
Expression toRemoveExpression= (Expression) toRemove;
Expression replacementExpression= (Expression) replacement;
ITypeBinding explicitCast= ASTNodes.getExplicitCast(replacementExpression, toRemoveExpression);
if (explicitCast != null) {
CastExpression cast= ast.newCastExpression();
if (NecessaryParenthesesChecker.needsParentheses(replacementExpression, cast, CastExpression.EXPRESSION_PROPERTY)) {
ParenthesizedExpression parenthesized= ast.newParenthesizedExpression();
parenthesized.setExpression(moved);
moved= parenthesized;
}
cast.setExpression(moved);
ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(toRemove, imports);
cast.setType(imports.addImport(explicitCast, ast, importRewriteContext, TypeLocation.CAST));
moved= cast;
}
rewrite.replace(toRemove, moved, null);
} else {
ASTNode parent= toRemove.getParent();
ASTNode moveTarget;
if ((parent instanceof Block || parent instanceof SwitchStatement) && replacement instanceof Block) {
ListRewrite listRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
List<Statement> list= ((Block) replacement).statements();
int lastIndex= list.size() - 1;
moveTarget= listRewrite.createMoveTarget(list.get(0), list.get(lastIndex));
} else {
moveTarget= rewrite.createMoveTarget(replacement);
}
rewrite.replace(toRemove, moveTarget, null);
}
proposals.add(proposal);
}
private static void addRemoveProposal(IInvocationContext context, ASTRewrite rewrite, String label, Collection<ICommandAccess> proposals) {
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 10, image);
proposals.add(proposal);
}
public static void getUnusedObjectAllocationProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit root= context.getASTRoot();
AST ast= root.getAST();
ASTNode selectedNode= problem.getCoveringNode(root);
if (selectedNode == null) {
return;
}
ASTNode parent= selectedNode.getParent();
if (parent instanceof ExpressionStatement) {
ExpressionStatement expressionStatement= (ExpressionStatement) parent;
Expression expr= expressionStatement.getExpression();
ITypeBinding exprType= expr.resolveTypeBinding();
if (exprType != null && Bindings.isSuperType(ast.resolveWellKnownType("java.lang.Throwable"), exprType)) { //$NON-NLS-1$
ASTRewrite rewrite= ASTRewrite.create(ast);
TightSourceRangeComputer sourceRangeComputer= new TightSourceRangeComputer();
rewrite.setTargetSourceRangeComputer(sourceRangeComputer);
ThrowStatement throwStatement= ast.newThrowStatement();
throwStatement.setExpression((Expression) rewrite.createMoveTarget(expr));
sourceRangeComputer.addTightSourceNode(expressionStatement);
rewrite.replace(expressionStatement, throwStatement, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_throw_allocated_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.THROW_ALLOCATED_OBJECT, image);
proposal.setEndPosition(rewrite.track(throwStatement));
proposals.add(proposal);
}
MethodDeclaration method= ASTResolving.findParentMethodDeclaration(selectedNode);
if (method != null && !method.isConstructor()) {
ASTRewrite rewrite= ASTRewrite.create(ast);
TightSourceRangeComputer sourceRangeComputer= new TightSourceRangeComputer();
rewrite.setTargetSourceRangeComputer(sourceRangeComputer);
ReturnStatement returnStatement= ast.newReturnStatement();
returnStatement.setExpression((Expression) rewrite.createMoveTarget(expr));
sourceRangeComputer.addTightSourceNode(expressionStatement);
rewrite.replace(expressionStatement, returnStatement, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_return_allocated_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
int relevance;
ITypeBinding returnTypeBinding= method.getReturnType2().resolveBinding();
if (returnTypeBinding != null && exprType != null && exprType.isAssignmentCompatible(returnTypeBinding)) {
relevance= IProposalRelevance.RETURN_ALLOCATED_OBJECT_MATCH;
} else if (method.getReturnType2() instanceof PrimitiveType
&& ((PrimitiveType) method.getReturnType2()).getPrimitiveTypeCode() == PrimitiveType.VOID) {
relevance= IProposalRelevance.RETURN_ALLOCATED_OBJECT_VOID;
} else {
relevance= IProposalRelevance.RETURN_ALLOCATED_OBJECT;
}
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, relevance, image);
proposal.setEndPosition(rewrite.track(returnStatement));
proposals.add(proposal);
}
{
ASTRewrite rewrite= ASTRewrite.create(ast);
rewrite.remove(parent, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_remove_allocated_description;
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REMOVE_UNUSED_ALLOCATED_OBJECT, image);
proposals.add(proposal);
}
}
QuickAssistProcessor.getAssignToVariableProposals(context, selectedNode, null, proposals);
}
public static void getAssignmentHasNoEffectProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit root= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(root);
if (!(selectedNode instanceof Assignment)) {
return;
}
ASTNode assignedNode= ((Assignment) selectedNode).getLeftHandSide();
ASTNode assignExpression= ((Assignment) selectedNode).getRightHandSide();
if (!(assignedNode instanceof SimpleName) && !(assignExpression instanceof SimpleName)) {
return;
}
IBinding binding= (assignedNode instanceof SimpleName) ? ((SimpleName) assignedNode).resolveBinding() : ((SimpleName) assignExpression).resolveBinding();
if (!(binding instanceof IVariableBinding)) {
return;
}
ITypeBinding typeBinding= Bindings.getBindingOfParentType(selectedNode);
if (typeBinding == null) {
return;
}
IVariableBinding fieldBinding= Bindings.findFieldInHierarchy(typeBinding, binding.getName());
if (fieldBinding == null || fieldBinding.getDeclaringClass() != typeBinding && Modifier.isPrivate(fieldBinding.getModifiers())) {
return;
}
if (binding != fieldBinding) {
if (assignedNode instanceof SimpleName) {
String label= CorrectionMessages.LocalCorrectionsSubProcessor_qualify_left_hand_side_description;
proposals.add(createNoSideEffectProposal(context, (SimpleName) assignedNode, fieldBinding, label, IProposalRelevance.QUALIFY_LHS));
}
if (assignExpression instanceof SimpleName) {
String label= CorrectionMessages.LocalCorrectionsSubProcessor_qualify_right_hand_side_description;
proposals.add(createNoSideEffectProposal(context, (SimpleName) assignExpression, fieldBinding, label, IProposalRelevance.QUALIFY_RHS));
}
}
if (binding == fieldBinding && ASTResolving.findParentBodyDeclaration(selectedNode) instanceof MethodDeclaration) {
SimpleName simpleName= (SimpleName) ((assignedNode instanceof SimpleName) ? assignedNode : assignExpression);
String label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createparameter_description, BasicElementLabels.getJavaElementName(simpleName.getIdentifier()));
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
proposals.add(new NewVariableCorrectionProposal(label, context.getCompilationUnit(), NewVariableCorrectionProposal.PARAM, simpleName, null, IProposalRelevance.CREATE_PARAMETER, image));
}
}
private static ASTRewriteCorrectionProposal createNoSideEffectProposal(IInvocationContext context, SimpleName nodeToQualify, IVariableBinding fieldBinding, String label, int relevance) {
AST ast= nodeToQualify.getAST();
Expression qualifier;
if (Modifier.isStatic(fieldBinding.getModifiers())) {
ITypeBinding declaringClass= fieldBinding.getDeclaringClass();
qualifier= ast.newSimpleName(declaringClass.getTypeDeclaration().getName());
} else {
qualifier= ast.newThisExpression();
}
ASTRewrite rewrite= ASTRewrite.create(ast);
FieldAccess access= ast.newFieldAccess();
access.setName((SimpleName) rewrite.createCopyTarget(nodeToQualify));
access.setExpression(qualifier);
rewrite.replace(nodeToQualify, access, null);
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
return new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, relevance, image);
}
public static void addValueForAnnotationProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ICompilationUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof Annotation) {
Annotation annotation= (Annotation) selectedNode;
if (annotation.resolveTypeBinding() == null) {
return;
}
MissingAnnotationAttributesProposal proposal= new MissingAnnotationAttributesProposal(cu, annotation, 10);
proposals.add(proposal);
}
}
public static void addTypePrametersToRawTypeReference(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
IProposableFix fix= Java50Fix.createRawTypeReferenceFix(context.getASTRoot(), problem);
if (fix != null) {
for (ICommandAccess element : proposals) {
if (element instanceof FixCorrectionProposal) {
FixCorrectionProposal fixProp= (FixCorrectionProposal) element;
if (RAW_TYPE_REFERENCE_ID.equals(fixProp.getCommandId())) {
return;
}
}
}
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
Map<String, String> options= new Hashtable<>();
options.put(CleanUpConstants.VARIABLE_DECLARATION_USE_TYPE_ARGUMENTS_FOR_RAW_TYPE_REFERENCES, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new Java50CleanUp(options), IProposalRelevance.RAW_TYPE_REFERENCE, image, context);
proposal.setCommandId(RAW_TYPE_REFERENCE_ID);
proposals.add(proposal);
}
//Infer Generic Type Arguments... proposal
boolean hasInferTypeArgumentsProposal= false;
for (ICommandAccess completionProposal : proposals) {
if (completionProposal instanceof ChangeCorrectionProposal) {
if (IJavaEditorActionDefinitionIds.INFER_TYPE_ARGUMENTS_ACTION.equals(((ChangeCorrectionProposal) completionProposal).getCommandId())) {
hasInferTypeArgumentsProposal= true;
break;
}
}
}
if (!hasInferTypeArgumentsProposal) {
final ICompilationUnit cu= context.getCompilationUnit();
ChangeCorrectionProposal proposal= new ChangeCorrectionProposal(CorrectionMessages.LocalCorrectionsSubProcessor_InferGenericTypeArguments, null,
IProposalRelevance.INFER_GENERIC_TYPE_ARGUMENTS, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE)) {
@Override
public void apply(IDocument document) {
IEditorInput input= new FileEditorInput((IFile) cu.getResource());
IWorkbenchPage p= JavaPlugin.getActivePage();
if (p == null)
return;
IEditorPart part= p.findEditor(input);
if (!(part instanceof JavaEditor))
return;
IEditorSite site= ((JavaEditor) part).getEditorSite();
InferTypeArgumentsAction action= new InferTypeArgumentsAction(site);
action.run(new StructuredSelection(cu));
}
@Override
public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
return CorrectionMessages.LocalCorrectionsSubProcessor_InferGenericTypeArguments_description;
}
};
proposal.setCommandId(IJavaEditorActionDefinitionIds.INFER_TYPE_ARGUMENTS_ACTION);
proposals.add(proposal);
}
addTypeArgumentsFromContext(context, problem, proposals);
}
private static void addTypeArgumentsFromContext(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
// similar to UnresolvedElementsSubProcessor.getTypeProposals(context, problem, proposals);
ICompilationUnit cu= context.getCompilationUnit();
CompilationUnit root= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(root);
if (selectedNode == null) {
return;
}
while (selectedNode.getLocationInParent() == QualifiedName.NAME_PROPERTY) {
selectedNode= selectedNode.getParent();
}
Name node= null;
if (selectedNode instanceof SimpleType) {
node= ((SimpleType) selectedNode).getName();
} else if (selectedNode instanceof NameQualifiedType) {
node= ((NameQualifiedType) selectedNode).getName();
} else if (selectedNode instanceof ArrayType) {
Type elementType= ((ArrayType) selectedNode).getElementType();
if (elementType.isSimpleType()) {
node= ((SimpleType) elementType).getName();
} else if (elementType.isNameQualifiedType()) {
node= ((NameQualifiedType) elementType).getName();
} else {
return;
}
} else if (selectedNode instanceof Name) {
node= (Name) selectedNode;
} else {
return;
}
// try to resolve type in context
ITypeBinding binding= ASTResolving.guessBindingForTypeReference(node);
if (binding != null) {
ASTNode parent= node.getParent();
if (parent instanceof Type && parent.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY && binding.isInterface()) { //bug 351853
return;
}
ITypeBinding simpleBinding= binding;
if (simpleBinding.isArray()) {
simpleBinding= simpleBinding.getElementType();
}
simpleBinding= simpleBinding.getTypeDeclaration();
if (!simpleBinding.isRecovered()) {
if (binding.isParameterizedType() && (node.getParent() instanceof SimpleType || node.getParent() instanceof NameQualifiedType) && !(node.getParent().getParent() instanceof Type)) {
proposals.add(UnresolvedElementsSubProcessor.createTypeRefChangeFullProposal(cu, binding, node, IProposalRelevance.TYPE_ARGUMENTS_FROM_CONTEXT, TypeLocation.TYPE_ARGUMENT));
}
}
} else {
ASTNode normalizedNode= ASTNodes.getNormalizedNode(node);
if (!(normalizedNode.getParent() instanceof Type) && node.getParent() != normalizedNode) {
ITypeBinding normBinding= ASTResolving.guessBindingForTypeReference(normalizedNode);
if (normBinding != null && !normBinding.isRecovered()) {
proposals.add(UnresolvedElementsSubProcessor.createTypeRefChangeFullProposal(cu, normBinding, normalizedNode, IProposalRelevance.TYPE_ARGUMENTS_FROM_CONTEXT,
TypeLocation.TYPE_ARGUMENT));
}
}
}
}
public static void addRemoveRedundantTypeArgumentsProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
IProposableFix fix= TypeParametersFix.createRemoveRedundantTypeArgumentsFix(context.getASTRoot(), problem);
if (fix != null) {
Image image= PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
Map<String, String> options= new HashMap<>();
options.put(CleanUpConstants.REMOVE_REDUNDANT_TYPE_ARGUMENTS, CleanUpOptions.TRUE);
FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new TypeParametersCleanUp(options), IProposalRelevance.REMOVE_REDUNDANT_TYPE_ARGUMENTS, image, context);
proposals.add(proposal);
}
}
public static void addFallThroughProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof SwitchCase && selectedNode.getLocationInParent() == SwitchStatement.STATEMENTS_PROPERTY) {
AST ast= selectedNode.getAST();
ASTNode parent= selectedNode.getParent();
// insert break:
ASTRewrite rewrite= ASTRewrite.create(ast);
ListRewrite listRewrite= rewrite.getListRewrite(parent, SwitchStatement.STATEMENTS_PROPERTY);
listRewrite.insertBefore(ast.newBreakStatement(), selectedNode, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_insert_break_statement;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.INSERT_BREAK_STATEMENT, image);
proposals.add(proposal);
// insert //$FALL-THROUGH$:
rewrite= ASTRewrite.create(ast);
rewrite.setTargetSourceRangeComputer(new NoCommentSourceRangeComputer());
listRewrite= rewrite.getListRewrite(parent, SwitchStatement.STATEMENTS_PROPERTY);
ASTNode fallThroughComment= rewrite.createStringPlaceholder("//$FALL-THROUGH$", ASTNode.EMPTY_STATEMENT); //$NON-NLS-1$
listRewrite.insertBefore(fallThroughComment, selectedNode, null);
label= CorrectionMessages.LocalCorrectionsSubProcessor_insert_fall_through;
image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.INSERT_FALL_THROUGH, image);
proposals.add(proposal);
}
}
public static void addCasesOmittedProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof Expression && selectedNode.getLocationInParent() == SwitchStatement.EXPRESSION_PROPERTY) {
AST ast= selectedNode.getAST();
SwitchStatement parent= (SwitchStatement) selectedNode.getParent();
for (Statement statement : (List<Statement>) parent.statements()) {
if (statement instanceof SwitchCase && ((SwitchCase) statement).isDefault()) {
// insert //$CASES-OMITTED$:
ASTRewrite rewrite= ASTRewrite.create(ast);
rewrite.setTargetSourceRangeComputer(new NoCommentSourceRangeComputer());
ListRewrite listRewrite= rewrite.getListRewrite(parent, SwitchStatement.STATEMENTS_PROPERTY);
ASTNode casesOmittedComment= rewrite.createStringPlaceholder("//$CASES-OMITTED$", ASTNode.EMPTY_STATEMENT); //$NON-NLS-1$
listRewrite.insertBefore(casesOmittedComment, statement, null);
String label= CorrectionMessages.LocalCorrectionsSubProcessor_insert_cases_omitted;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.INSERT_CASES_OMITTED, image);
proposals.add(proposal);
break;
}
}
}
}
public static void addDeprecatedFieldsToMethodsProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof Name) {
IBinding binding= ((Name) selectedNode).resolveBinding();
if (binding instanceof IVariableBinding) {
IVariableBinding variableBinding= (IVariableBinding) binding;
if (variableBinding.isField()) {
String qualifiedName= variableBinding.getDeclaringClass().getTypeDeclaration().getQualifiedName();
String fieldName= variableBinding.getName();
String[] methodName= getMethod(JavaModelUtil.concatenateName(qualifiedName, fieldName));
if (methodName != null) {
AST ast= selectedNode.getAST();
ASTRewrite astRewrite= ASTRewrite.create(ast);
ImportRewrite importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);
MethodInvocation method= ast.newMethodInvocation();
String qfn= importRewrite.addImport(methodName[0]);
method.setExpression(ast.newName(qfn));
method.setName(ast.newSimpleName(methodName[1]));
ASTNode parent= selectedNode.getParent();
ICompilationUnit cu= context.getCompilationUnit();
// add explicit type arguments if necessary (for 1.8 and later, we're optimistic that inference just works):
if (Invocations.isInvocationWithArguments(parent) && !JavaModelUtil.is1d8OrHigher(cu.getJavaProject())) {
IMethodBinding methodBinding= Invocations.resolveBinding(parent);
if (methodBinding != null) {
ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
int i= Invocations.getArguments(parent).indexOf(selectedNode);
if (parameterTypes.length >= i && parameterTypes[i].isParameterizedType()) {
ITypeBinding[] typeArguments= parameterTypes[i].getTypeArguments();
for (ITypeBinding typeArgument : typeArguments) {
typeArgument= Bindings.normalizeForDeclarationUse(typeArgument, ast);
if (!TypeRules.isJavaLangObject(typeArgument)) {
// add all type arguments if at least one is found to be necessary:
List<Type> typeArgumentsList= method.typeArguments();
for (ITypeBinding t : typeArguments) {
typeArgument= Bindings.normalizeForDeclarationUse(t, ast);
typeArgumentsList.add(importRewrite.addImport(typeArgument, ast));
}
break;
}
}
}
}
}
astRewrite.replace(selectedNode, method, null);
String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_replacefieldaccesswithmethod_description,
BasicElementLabels.getJavaElementName(ASTNodes.asString(method)));
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, astRewrite, IProposalRelevance.REPLACE_FIELD_ACCESS_WITH_METHOD, image);
proposal.setImportRewrite(importRewrite);
proposals.add(proposal);
}
}
}
}
}
private static Map<String, String[]> resolveMap;
private static String[] getMethod(String fieldName) {
if (resolveMap == null) {
resolveMap= new HashMap<>();
resolveMap.put("java.util.Collections.EMPTY_MAP", new String[] { "java.util.Collections", "emptyMap" }); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
resolveMap.put("java.util.Collections.EMPTY_SET", new String[] { "java.util.Collections", "emptySet" }); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
resolveMap.put("java.util.Collections.EMPTY_LIST", new String[] { "java.util.Collections", "emptyList" });//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
return resolveMap.get(fieldName);
}
public static void getMissingEnumConstantCaseProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
for (ICommandAccess proposal : proposals) {
if (proposal instanceof ChangeCorrectionProposal) {
if (CorrectionMessages.LocalCorrectionsSubProcessor_add_missing_cases_description.equals(((ChangeCorrectionProposal) proposal).getName())) {
return;
}
}
}
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof Expression) {
StructuralPropertyDescriptor locationInParent= selectedNode.getLocationInParent();
ASTNode parent= selectedNode.getParent();
ITypeBinding binding;
List<Statement> statements;
if (locationInParent == SwitchStatement.EXPRESSION_PROPERTY) {
SwitchStatement statement= (SwitchStatement) parent;
binding= statement.getExpression().resolveTypeBinding();
statements= statement.statements();
} else if (locationInParent == SwitchExpression.EXPRESSION_PROPERTY) {
SwitchExpression switchExpression= (SwitchExpression) parent;
binding= switchExpression.getExpression().resolveTypeBinding();
statements= switchExpression.statements();
} else {
return;
}
if (binding == null || !binding.isEnum()) {
return;
}
ArrayList<String> missingEnumCases= new ArrayList<>();
boolean hasDefault= evaluateMissingSwitchCases(binding, statements, missingEnumCases);
if (missingEnumCases.size() == 0 && hasDefault)
return;
createMissingCaseProposals(context, parent, missingEnumCases, proposals);
}
}
@SuppressWarnings("deprecation")
public static boolean evaluateMissingSwitchCases(ITypeBinding enumBindings, List<Statement> switchStatements, ArrayList<String> enumConstNames) {
for (IVariableBinding field : enumBindings.getDeclaredFields()) {
if (field.isEnumConstant()) {
enumConstNames.add(field.getName());
}
}
boolean hasDefault= false;
for (Statement curr : switchStatements) {
if (curr instanceof SwitchCase) {
SwitchCase switchCase= (SwitchCase) curr;
if (ASTHelper.isSwitchCaseExpressionsSupportedInAST(switchCase.getAST())) {
List<Expression> expressions= switchCase.expressions();
if (expressions.size() == 0) {
hasDefault= true;
} else {
for (Expression expression : expressions) {
if (expression instanceof SimpleName) {
enumConstNames.remove(((SimpleName) expression).getFullyQualifiedName());
}
}
}
} else {
Expression expression= ((SwitchCase) curr).getExpression();
if (expression instanceof SimpleName) {
enumConstNames.remove(((SimpleName) expression).getFullyQualifiedName());
} else if (expression == null) {
hasDefault= true;
}
}
}
}
return hasDefault;
}
@SuppressWarnings("deprecation")
public static void createMissingCaseProposals(IInvocationContext context, ASTNode parent, ArrayList<String> enumConstNames, Collection<ICommandAccess> proposals) {
List<Statement> statements;
Expression expression;
if (parent instanceof SwitchStatement) {
SwitchStatement switchStatement= (SwitchStatement) parent;
statements= switchStatement.statements();
expression= switchStatement.getExpression();
} else if (parent instanceof SwitchExpression) {
SwitchExpression switchExpression= (SwitchExpression) parent;
statements= switchExpression.statements();
expression= switchExpression.getExpression();
} else {
return;
}
int defaultIndex= statements.size();
for (int i= 0; i < statements.size(); i++) {
Statement curr= statements.get(i);
if (curr instanceof SwitchCase) {
SwitchCase switchCase= (SwitchCase) curr;
if (ASTHelper.isSwitchCaseExpressionsSupportedInAST(switchCase.getAST())) {
if (switchCase.expressions().size() == 0) {
defaultIndex= i;
break;
}
} else if (switchCase.getExpression() == null) {
defaultIndex= i;
break;
}
}
}
boolean hasDefault= defaultIndex < statements.size();
AST ast= parent.getAST();
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
if (enumConstNames.size() > 0) {
ASTRewrite astRewrite= ASTRewrite.create(ast);
ListRewrite listRewrite;
if (parent instanceof SwitchStatement) {
listRewrite= astRewrite.getListRewrite(parent, SwitchStatement.STATEMENTS_PROPERTY);
} else {
listRewrite= astRewrite.getListRewrite(parent, SwitchExpression.STATEMENTS_PROPERTY);
}
String label= CorrectionMessages.LocalCorrectionsSubProcessor_add_missing_cases_description;
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), astRewrite, IProposalRelevance.ADD_MISSING_CASE_STATEMENTS, image);
for (String enumConstName : enumConstNames) {
SwitchCase newSwitchCase= ast.newSwitchCase();
Name newName= ast.newName(enumConstName);
if (ASTHelper.isSwitchCaseExpressionsSupportedInAST(ast)) {
newSwitchCase.expressions().add(newName);
} else {
newSwitchCase.setExpression(newName);
}
listRewrite.insertAt(newSwitchCase, defaultIndex, null);
defaultIndex++;
if (!hasDefault) {
if (ASTHelper.isSwitchExpressionNodeSupportedInAST(ast)) {
if (statements.size() > 0) {
Statement firstStatement= statements.get(0);
SwitchCase switchCase= (SwitchCase) firstStatement;
boolean isArrow= switchCase.isSwitchLabeledRule();
newSwitchCase.setSwitchLabeledRule(isArrow);
if (isArrow || parent instanceof SwitchExpression) {
ThrowStatement newThrowStatement= getThrowForUnsupportedCase(expression, ast, astRewrite);
listRewrite.insertLast(newThrowStatement, null);
proposal.addLinkedPosition(astRewrite.track(newThrowStatement), true, enumConstName);
} else {
listRewrite.insertAt(ast.newBreakStatement(), defaultIndex, null);
}
} else {
listRewrite.insertAt(ast.newBreakStatement(), defaultIndex, null);
}
} else {
listRewrite.insertAt(ast.newBreakStatement(), defaultIndex, null);
}
defaultIndex++;
}
}
if (!hasDefault) {
SwitchCase newSwitchCase= ast.newSwitchCase();
listRewrite.insertAt(newSwitchCase, defaultIndex, null);
defaultIndex++;
if (ASTHelper.isSwitchExpressionNodeSupportedInAST(ast)) {
if (statements.size() > 0) {
Statement firstStatement= statements.get(0);
SwitchCase switchCase= (SwitchCase) firstStatement;
boolean isArrow= switchCase.isSwitchLabeledRule();
newSwitchCase.setSwitchLabeledRule(isArrow);
if (isArrow || parent instanceof SwitchExpression) {
ThrowStatement newThrowStatement= getThrowForUnexpectedDefault(expression, ast, astRewrite);
listRewrite.insertLast(newThrowStatement, null);
proposal.addLinkedPosition(astRewrite.track(newThrowStatement), true, "defaultCase"); //$NON-NLS-1$
} else {
listRewrite.insertAt(ast.newBreakStatement(), defaultIndex, null);
}
} else {
listRewrite.insertAt(ast.newBreakStatement(), defaultIndex, null);
}
} else {
newSwitchCase.setExpression(null);
listRewrite.insertAt(ast.newBreakStatement(), defaultIndex, null);
}
}
proposals.add(proposal);
}
if (!hasDefault) {
createMissingDefaultProposal(context, parent, image, proposals);
}
}
private static ThrowStatement getThrowForUnsupportedCase(Expression switchExpr, AST ast, ASTRewrite astRewrite) {
ThrowStatement newThrowStatement= ast.newThrowStatement();
ClassInstanceCreation newCic= ast.newClassInstanceCreation();
newCic.setType(ast.newSimpleType(ast.newSimpleName("UnsupportedOperationException"))); //$NON-NLS-1$
InfixExpression newInfixExpr= ast.newInfixExpression();
StringLiteral newStringLiteral= ast.newStringLiteral();
newStringLiteral.setLiteralValue("Unimplemented case: "); //$NON-NLS-1$
newInfixExpr.setLeftOperand(newStringLiteral);
newInfixExpr.setOperator(InfixExpression.Operator.PLUS);
newInfixExpr.setRightOperand((Expression) astRewrite.createCopyTarget(switchExpr));
newCic.arguments().add(newInfixExpr);
newThrowStatement.setExpression(newCic);
return newThrowStatement;
}
public static void addMissingDefaultCaseProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode instanceof Expression) {
StructuralPropertyDescriptor locationInParent= selectedNode.getLocationInParent();
ASTNode parent= selectedNode.getParent();
List<Statement> statements;
if (locationInParent == SwitchStatement.EXPRESSION_PROPERTY) {
statements= ((SwitchStatement) parent).statements();
} else if (locationInParent == SwitchExpression.EXPRESSION_PROPERTY) {
statements= ((SwitchExpression) parent).statements();
} else {
return;
}
for (Statement statement : statements) {
if (statement instanceof SwitchCase && ((SwitchCase) statement).isDefault()) {
return;
}
}
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
createMissingDefaultProposal(context, parent, image, proposals);
}
}
@SuppressWarnings("deprecation")
private static void createMissingDefaultProposal(IInvocationContext context, ASTNode parent, Image image, Collection<ICommandAccess> proposals) {
List<Statement> statements;
Expression expression;
if (parent instanceof SwitchStatement) {
SwitchStatement switchStatement= (SwitchStatement) parent;
statements= switchStatement.statements();
expression= switchStatement.getExpression();
} else if (parent instanceof SwitchExpression) {
SwitchExpression switchExpression= (SwitchExpression) parent;
statements= switchExpression.statements();
expression= switchExpression.getExpression();
} else {
return;
}
AST ast= parent.getAST();
ASTRewrite astRewrite= ASTRewrite.create(ast);
ListRewrite listRewrite;
if (parent instanceof SwitchStatement) {
listRewrite= astRewrite.getListRewrite(parent, SwitchStatement.STATEMENTS_PROPERTY);
} else {
listRewrite= astRewrite.getListRewrite(parent, SwitchExpression.STATEMENTS_PROPERTY);
}
String label= CorrectionMessages.LocalCorrectionsSubProcessor_add_default_case_description;
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), astRewrite, IProposalRelevance.ADD_MISSING_DEFAULT_CASE, image);
SwitchCase newSwitchCase= ast.newSwitchCase();
listRewrite.insertLast(newSwitchCase, null);
if (ASTHelper.isSwitchCaseExpressionsSupportedInAST(ast)) {
boolean isArrow= false;
if (statements.size() > 0) {
Statement firstStatement= statements.get(0);
SwitchCase switchCase= (SwitchCase) firstStatement;
isArrow= switchCase.isSwitchLabeledRule();
newSwitchCase.setSwitchLabeledRule(isArrow);
}
if (isArrow || parent instanceof SwitchExpression) {
ThrowStatement newThrowStatement= getThrowForUnexpectedDefault(expression, ast, astRewrite);
listRewrite.insertLast(newThrowStatement, null);
proposal.addLinkedPosition(astRewrite.track(newThrowStatement), true, null);
} else {
listRewrite.insertLast(ast.newBreakStatement(), null);
}
} else {
newSwitchCase.setExpression(null);
listRewrite.insertLast(ast.newBreakStatement(), null);
}
proposals.add(proposal);
}
private static ThrowStatement getThrowForUnexpectedDefault(Expression switchExpression, AST ast, ASTRewrite astRewrite) {
ThrowStatement newThrowStatement= ast.newThrowStatement();
ClassInstanceCreation newCic= ast.newClassInstanceCreation();
newCic.setType(ast.newSimpleType(ast.newSimpleName("IllegalArgumentException"))); //$NON-NLS-1$
InfixExpression newInfixExpr= ast.newInfixExpression();
StringLiteral newStringLiteral= ast.newStringLiteral();
newStringLiteral.setLiteralValue("Unexpected value: "); //$NON-NLS-1$
newInfixExpr.setLeftOperand(newStringLiteral);
newInfixExpr.setOperator(InfixExpression.Operator.PLUS);
newInfixExpr.setRightOperand((Expression) astRewrite.createCopyTarget(switchExpression));
newCic.arguments().add(newInfixExpr);
newThrowStatement.setExpression(newCic);
return newThrowStatement;
}
public static void addMissingHashCodeProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
final ICompilationUnit cu= context.getCompilationUnit();
CompilationUnit astRoot= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(astRoot);
if (!(selectedNode instanceof Name)) {
return;
}
StructuralPropertyDescriptor locationInParent= selectedNode.getLocationInParent();
if (locationInParent != TypeDeclaration.NAME_PROPERTY && locationInParent != EnumDeclaration.NAME_PROPERTY) {
return;
}
AbstractTypeDeclaration typeDeclaration= (AbstractTypeDeclaration) selectedNode.getParent();
ITypeBinding binding= typeDeclaration.resolveBinding();
if (binding == null || binding.getSuperclass() == null) {
return;
}
final IType type= (IType) binding.getJavaElement();
boolean hasInstanceFields= false;
for (IVariableBinding declaredField : binding.getDeclaredFields()) {
if (!Modifier.isStatic(declaredField.getModifiers())) {
hasInstanceFields= true;
break;
}
}
if (hasInstanceFields) {
//Generate hashCode() and equals()... proposal
String label= CorrectionMessages.LocalCorrectionsSubProcessor_generate_hashCode_equals_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ChangeCorrectionProposal proposal= new ChangeCorrectionProposal(label, null, IProposalRelevance.GENERATE_HASHCODE_AND_EQUALS, image) {
@Override
public void apply(IDocument document) {
IEditorInput input= new FileEditorInput((IFile) cu.getResource());
IWorkbenchPage p= JavaPlugin.getActivePage();
if (p == null)
return;
IEditorPart part= p.findEditor(input);
if (!(part instanceof JavaEditor))
return;
IEditorSite site= ((JavaEditor) part).getEditorSite();
GenerateHashCodeEqualsAction action= new GenerateHashCodeEqualsAction(site);
action.run(new StructuredSelection(type));
}
@Override
public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
return CorrectionMessages.LocalCorrectionsSubProcessor_generate_hashCode_equals_additional_info;
}
};
proposals.add(proposal);
}
//Override hashCode() proposal
IMethodBinding superHashCode= Bindings.findMethodInHierarchy(binding, "hashCode", new ITypeBinding[0]); //$NON-NLS-1$
if (superHashCode == null) {
return;
}
String label= CorrectionMessages.LocalCorrectionsSubProcessor_override_hashCode_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC);
ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
LinkedCorrectionProposal proposal2= new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.OVERRIDE_HASHCODE, image);
ImportRewrite importRewrite= proposal2.createImportRewrite(astRoot);
final CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(cu);
try {
ImportRewriteContext importContext= new ContextSensitiveImportRewriteContext(astRoot, problem.getOffset(), importRewrite);
MethodDeclaration hashCode= StubUtility2.createImplementationStub(cu, rewrite, importRewrite, importContext, superHashCode, binding, settings, false, null);
BodyDeclarationRewrite.create(rewrite, typeDeclaration).insert(hashCode, null);
proposal2.setEndPosition(rewrite.track(hashCode));
} catch (CoreException e) {
JavaPlugin.log(e);
}
proposals.add(proposal2);
}
public static void getGenerateForLoopProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode coveringNode= problem.getCoveringNode(context.getASTRoot());
if (coveringNode != null) {
QuickAssistProcessor.getGenerateForLoopProposals(context, coveringNode, null, proposals);
}
}
public static void getConvertLambdaToAnonymousClassCreationsProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
ASTNode coveringNode= problem.getCoveringNode(context.getASTRoot());
if (coveringNode != null) {
QuickAssistProcessor.getConvertLambdaToAnonymousClassCreationsProposals(context, coveringNode, proposals);
}
}
public static void addOverrideDefaultMethodProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
CompilationUnit astRoot= context.getASTRoot();
ASTNode selectedNode= problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
StructuralPropertyDescriptor locationInParent= selectedNode.getLocationInParent();
if (locationInParent != TypeDeclaration.NAME_PROPERTY && locationInParent != EnumDeclaration.NAME_PROPERTY) {
return;
}
ASTNode typeNode= selectedNode.getParent();
if (typeNode == null) {
return;
}
ITypeBinding typeBinding= ((AbstractTypeDeclaration) typeNode).resolveBinding();
if (typeBinding == null) {
return;
}
if (problem.getProblemId() == IProblem.DuplicateInheritedDefaultMethods) {
String[] args= problem.getProblemArguments();
if (args.length < 5) {
return;
}
String methodName= args[0];
if (methodName == null) {
return;
}
String[] parameters1= {};
if (args[1] != null && args[1].length() != 0) {
parameters1= args[1].split(", "); //$NON-NLS-1$
}
String[] parameters2= {};
if (args[2] != null && args[2].length() != 0) {
parameters2= args[2].split(", "); //$NON-NLS-1$
}
addOverrideProposal(typeNode, typeBinding, methodName, parameters1, args[3], context, proposals);
addOverrideProposal(typeNode, typeBinding, methodName, parameters2, args[4], context, proposals);
} else if (problem.getProblemId() == IProblem.InheritedDefaultMethodConflictsWithOtherInherited) {
String[] args= problem.getProblemArguments();
if (args.length < 3) {
return;
}
String arg0= args[0];
if (arg0 == null) {
return;
}
int indexOfLParen= arg0.indexOf('(');
if (indexOfLParen == -1) {
return;
}
int indexOfRParen= arg0.indexOf(')');
if (indexOfRParen == -1) {
return;
}
String methodName= arg0.substring(0, indexOfLParen);
String paramString= arg0.substring(indexOfLParen + 1, indexOfRParen);
String[] parameters= {};
if (paramString != null && paramString.length() != 0) {
parameters= paramString.split(", "); //$NON-NLS-1$
}
addOverrideProposal(typeNode, typeBinding, methodName, parameters, args[1], context, proposals);
addOverrideProposal(typeNode, typeBinding, methodName, parameters, args[2], context, proposals);
}
}
private static void addOverrideProposal(ASTNode typeNode, ITypeBinding typeBinding, String methodName, String[] parameters, String superType,
IInvocationContext context, Collection<ICommandAccess> proposals) {
ITypeBinding superTypeBinding= null;
if (superType != null) {
int i= superType.indexOf('<');
if (i > 0) {
superType= superType.substring(0, i);
}
superTypeBinding= Bindings.findTypeInHierarchy(typeBinding, superType);
}
if (superTypeBinding == null) {
return;
}
IMethodBinding methodToOverride= Bindings.findMethodWithDeclaredParameterTypesInType(superTypeBinding, methodName, parameters);
if (methodToOverride == null) {
return;
}
String label;
int modifiers= methodToOverride.getModifiers();
if (Modifier.isDefault(modifiers)) {
label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_override_default_method_description, superTypeBinding.getName());
} else if (Modifier.isAbstract(modifiers)) {
label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_implement_method_description, superTypeBinding.getName());
} else {
label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_override_method_description, superTypeBinding.getName());
}
Image image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC);
CompilationUnit astRoot= context.getASTRoot();
ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
ICompilationUnit cu= context.getCompilationUnit();
LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, IProposalRelevance.OVERRIDE_DEFAULT_METHOD, image);
ImportRewrite importRewrite= proposal.createImportRewrite(astRoot);
ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(astRoot, typeNode.getStartPosition(), importRewrite);
CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(cu);
try {
MethodDeclaration stub= StubUtility2.createImplementationStub(cu, rewrite, importRewrite, importRewriteContext, methodToOverride, typeBinding, settings,
typeBinding.isInterface(), new NodeFinder(astRoot, typeNode.getStartPosition(), 0).getCoveringNode());
BodyDeclarationRewrite.create(rewrite, typeNode).insert(stub, null);
proposal.setEndPosition(rewrite.track(stub));
} catch (CoreException e) {
JavaPlugin.log(e);
}
proposals.add(proposal);
}
public static void addServiceProviderProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ASTNode node= problem.getCoveredNode(context.getASTRoot());
if (!(node instanceof Name) && !(node.getParent() instanceof ProvidesDirective)) {
return;
}
Name name= (Name) node;
ProvidesDirective prov= (ProvidesDirective) name.getParent();
ITypeBinding targetBinding= name.resolveTypeBinding();
ITypeBinding serviceBinding= prov.getName().resolveTypeBinding();
if (targetBinding != null && serviceBinding != null) {
ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(context.getCompilationUnit(), context.getASTRoot(), targetBinding);
IJavaProject proj= context.getCompilationUnit().getJavaProject();
IType type= proj.findType(serviceBinding.getQualifiedName());
Image image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC);
proposals.add(new NewProviderMethodDeclaration(
Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_add_provider_method_description, type.getElementName()),
targetCU, context.getASTRoot(), targetBinding,
IProposalRelevance.CREATE_METHOD, image, type));
}
}
public static void addServiceProviderConstructorProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
ASTNode node= problem.getCoveredNode(context.getASTRoot());
if (!(node instanceof Name) && !(node.getParent() instanceof ProvidesDirective)) {
return;
}
Name name= (Name) node;
ITypeBinding targetBinding= name.resolveTypeBinding();
if (targetBinding != null &&
!targetBinding.isInterface()
&& !Modifier.isAbstract(targetBinding.getModifiers())) {
ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(context.getCompilationUnit(), context.getASTRoot(), targetBinding);
IJavaProject proj= targetCU.getJavaProject();
// Get the AST Root (CompilationUnit) for target class
ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(targetCU);
parser.setProject(proj);
parser.setUnitName(targetCU.getPath().toString());
parser.setResolveBindings(true);
ASTNode targetRoot= parser.createAST(null);
if (!(targetRoot instanceof CompilationUnit)) {
return;
}
IType targetType= proj.findType(targetBinding.getQualifiedName());
// Locate the no-arg constructor binding for the type
List<IMethodBinding> result= Arrays.asList(targetBinding.getDeclaredMethods()).stream()
.filter(m -> m.isConstructor() && m.getParameterTypes().length == 0)
.collect(Collectors.toList());
// no-arg constructor exists, need to change visibility
if (!result.isEmpty()) {
IMethodBinding targetMethodBinding= result.get(0);
IMethod targetMethod= null;
for (IMethod m : targetType.getMethods()) {
if (m.isConstructor() && m.getParameters().length == 0) {
targetMethod= m;
break;
}
}
String label= CorrectionMessages.LocalCorrectionsSubProcessor_changeconstructor_public_description;
int include= Modifier.PUBLIC;
int exclude= Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
// Locate the constructor declaration node in the target AST Node
MethodDeclaration targetMethodDecl= ASTNodeSearchUtil.getMethodDeclarationNode(targetMethod, (CompilationUnit) targetRoot);
proposals.add(new ModifierChangeCorrectionProposal(label, targetCU, targetMethodBinding, targetMethodDecl.getName(),
include, exclude, IProposalRelevance.CHANGE_VISIBILITY_TO_NON_PRIVATE,
JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE)));
} else {
// no-arg constructor does not exist, need to create it
String[] args= new String[] { org.eclipse.jdt.internal.ui.text.correction.ASTResolving
.getMethodSignature(org.eclipse.jdt.internal.ui.text.correction.ASTResolving.getTypeSignature(targetBinding), new ITypeBinding[0], false) };
String label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createconstructor_description, args);
Image image= JavaElementImageProvider.getDecoratedImage(JavaPluginImages.DESC_MISC_PUBLIC, JavaElementImageDescriptor.CONSTRUCTOR, JavaElementImageProvider.SMALL_SIZE);
proposals.add(new NewMethodCorrectionProposal(label, targetCU, targetRoot, new ArrayList<>(), targetBinding, IProposalRelevance.CREATE_CONSTRUCTOR, image));
}
}
}
private LocalCorrectionsSubProcessor() {
}
}