blob: 1a21adce01cf325739c812ea3b66e0cafff96290 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.text.correction;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.graphics.Image;
import org.eclipse.jdt.core.CorrectionEngine;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
/**
*
*/
public class SuppressWarningsSubProcessor {
private static final String ADD_SUPPRESSWARNINGS_ID= "org.eclipse.jdt.ui.correction.addSuppressWarnings"; //$NON-NLS-1$
public static final boolean hasSuppressWarningsProposal(int problemId) {
return CorrectionEngine.getWarningToken(problemId) != null; // Suppress warning annotations
}
public static void addSuppressWarningsProposals(IInvocationContext context, IProblemLocation problem, Collection proposals) {
if (problem.isError()) {
return;
}
String warningToken= CorrectionEngine.getWarningToken(problem.getProblemId());
if (warningToken == null) {
return;
}
for (Iterator iter= proposals.iterator(); iter.hasNext();) {
Object element= iter.next();
if (element instanceof SuppressWarningsProposal && warningToken.equals(((SuppressWarningsProposal) element).getWarningToken())) {
return; // only one at a time
}
}
ASTNode node= problem.getCoveringNode(context.getASTRoot());
if (node == null) {
return;
}
if (node.getLocationInParent() == VariableDeclarationFragment.NAME_PROPERTY) {
ASTNode parent= node.getParent();
if (parent.getLocationInParent() == VariableDeclarationStatement.FRAGMENTS_PROPERTY) {
addSuppressWarningsProposal(context.getCompilationUnit(), parent.getParent(), warningToken, -2, proposals);
return;
}
} else if (node.getLocationInParent() == SingleVariableDeclaration.NAME_PROPERTY) {
addSuppressWarningsProposal(context.getCompilationUnit(), node.getParent(), warningToken, -2, proposals);
return;
} else if (node.getLocationInParent() == VariableDeclarationFragment.INITIALIZER_PROPERTY) {
node= ASTResolving.findParentBodyDeclaration(node);
if (node instanceof FieldDeclaration) {
node= node.getParent();
}
}
ASTNode target= ASTResolving.findParentBodyDeclaration(node);
if (target instanceof Initializer) {
target= ASTResolving.findParentBodyDeclaration(target.getParent());
}
if (target != null) {
addSuppressWarningsProposal(context.getCompilationUnit(), target, warningToken, -3, proposals);
}
}
private static String getFirstFragmentName(List fragments) {
if (fragments.size() > 0) {
return ((VariableDeclarationFragment) fragments.get(0)).getName().getIdentifier();
}
return new String();
}
private static class SuppressWarningsProposal extends ASTRewriteCorrectionProposal {
private final String fWarningToken;
private final ASTNode fNode;
private final ChildListPropertyDescriptor fProperty;
public SuppressWarningsProposal(String warningToken, String label, ICompilationUnit cu, ASTNode node, ChildListPropertyDescriptor property, int relevance) {
super(label, cu, null, relevance, JavaPluginImages.get(JavaPluginImages.IMG_OBJS_ANNOTATION));
fWarningToken= warningToken;
fNode= node;
fProperty= property;
setCommandId(ADD_SUPPRESSWARNINGS_ID);
}
/**
* @return Returns the warningToken.
*/
public String getWarningToken() {
return fWarningToken;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite()
*/
protected ASTRewrite getRewrite() throws CoreException {
AST ast= fNode.getAST();
ASTRewrite rewrite= ASTRewrite.create(ast);
StringLiteral newStringLiteral= ast.newStringLiteral();
newStringLiteral.setLiteralValue(fWarningToken);
Annotation existing= findExistingAnnotation((List) fNode.getStructuralProperty(fProperty));
if (existing == null) {
ListRewrite listRewrite= rewrite.getListRewrite(fNode, fProperty);
SingleMemberAnnotation newAnnot= ast.newSingleMemberAnnotation();
newAnnot.setTypeName(ast.newSimpleName("SuppressWarnings")); //$NON-NLS-1$
newAnnot.setValue(newStringLiteral);
listRewrite.insertFirst(newAnnot, null);
} else if (existing instanceof SingleMemberAnnotation) {
SingleMemberAnnotation annotation= (SingleMemberAnnotation) existing;
Expression value= annotation.getValue();
if (!addSuppressArgument(rewrite, value, newStringLiteral)) {
rewrite.set(existing, SingleMemberAnnotation.VALUE_PROPERTY, newStringLiteral, null);
}
} else if (existing instanceof NormalAnnotation) {
NormalAnnotation annotation= (NormalAnnotation) existing;
Expression value= findValue(annotation.values());
if (!addSuppressArgument(rewrite, value, newStringLiteral)) {
ListRewrite listRewrite= rewrite.getListRewrite(annotation, NormalAnnotation.VALUES_PROPERTY);
MemberValuePair pair= ast.newMemberValuePair();
pair.setName(ast.newSimpleName("value")); //$NON-NLS-1$
pair.setValue(newStringLiteral);
listRewrite.insertFirst(pair, null);
}
}
return rewrite;
}
private static boolean addSuppressArgument(ASTRewrite rewrite, Expression value, StringLiteral newStringLiteral) {
if (value instanceof ArrayInitializer) {
ListRewrite listRewrite= rewrite.getListRewrite(value, ArrayInitializer.EXPRESSIONS_PROPERTY);
listRewrite.insertLast(newStringLiteral, null);
} else if (value instanceof StringLiteral) {
ArrayInitializer newArr= rewrite.getAST().newArrayInitializer();
newArr.expressions().add(rewrite.createMoveTarget(value));
newArr.expressions().add(newStringLiteral);
rewrite.replace(value, newArr, null);
} else {
return false;
}
return true;
}
private static Expression findValue(List keyValues) {
for (int i= 0, len= keyValues.size(); i < len; i++) {
MemberValuePair curr= (MemberValuePair) keyValues.get(i);
if ("value".equals(curr.getName().getIdentifier())) { //$NON-NLS-1$
return curr.getValue();
}
}
return null;
}
private static Annotation findExistingAnnotation(List modifiers) {
for (int i= 0, len= modifiers.size(); i < len; i++) {
Object curr= modifiers.get(i);
if (curr instanceof NormalAnnotation || curr instanceof SingleMemberAnnotation) {
Annotation annotation= (Annotation) curr;
String fullyQualifiedName= annotation.getTypeName().getFullyQualifiedName();
if ("SuppressWarnings".equals(fullyQualifiedName) || "java.lang.SuppressWarnings".equals(fullyQualifiedName)) { //$NON-NLS-1$ //$NON-NLS-2$
return annotation;
}
}
}
return null;
}
}
private static void addSuppressWarningsProposal(ICompilationUnit cu, ASTNode node, String warningToken, int relevance, Collection proposals) {
ChildListPropertyDescriptor property= null;
String name;
switch (node.getNodeType()) {
case ASTNode.SINGLE_VARIABLE_DECLARATION:
property= SingleVariableDeclaration.MODIFIERS2_PROPERTY;
name= ((SingleVariableDeclaration) node).getName().getIdentifier();
break;
case ASTNode.VARIABLE_DECLARATION_STATEMENT:
property= VariableDeclarationStatement.MODIFIERS2_PROPERTY;
name= getFirstFragmentName(((VariableDeclarationStatement) node).fragments());
break;
case ASTNode.TYPE_DECLARATION:
property= TypeDeclaration.MODIFIERS2_PROPERTY;
name= ((TypeDeclaration) node).getName().getIdentifier();
break;
case ASTNode.ANNOTATION_TYPE_DECLARATION:
property= AnnotationTypeDeclaration.MODIFIERS2_PROPERTY;
name= ((AnnotationTypeDeclaration) node).getName().getIdentifier();
break;
case ASTNode.ENUM_DECLARATION:
property= EnumDeclaration.MODIFIERS2_PROPERTY;
name= ((EnumDeclaration) node).getName().getIdentifier();
break;
case ASTNode.FIELD_DECLARATION:
property= FieldDeclaration.MODIFIERS2_PROPERTY;
name= getFirstFragmentName(((FieldDeclaration) node).fragments());
break;
case ASTNode.INITIALIZER:
property= Initializer.MODIFIERS2_PROPERTY;
name= CorrectionMessages.SuppressWarningsSubProcessor_suppress_warnings_initializer_label;
break;
case ASTNode.METHOD_DECLARATION:
property= MethodDeclaration.MODIFIERS2_PROPERTY;
name= ((MethodDeclaration) node).getName().getIdentifier() + "()"; //$NON-NLS-1$
break;
case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
property= AnnotationTypeMemberDeclaration.MODIFIERS2_PROPERTY;
name= ((AnnotationTypeMemberDeclaration) node).getName().getIdentifier() + "()"; //$NON-NLS-1$
break;
case ASTNode.ENUM_CONSTANT_DECLARATION:
property= EnumConstantDeclaration.MODIFIERS2_PROPERTY;
name= ((EnumConstantDeclaration) node).getName().getIdentifier();
break;
default:
JavaPlugin.logErrorMessage("SuppressWarning quick fix: wrong node kind: " + node.getNodeType()); //$NON-NLS-1$
return;
}
String label= Messages.format(CorrectionMessages.SuppressWarningsSubProcessor_suppress_warnings_label, new String[] { warningToken, name });
ASTRewriteCorrectionProposal proposal= new SuppressWarningsProposal(warningToken, label, cu, node, property, relevance);
proposals.add(proposal);
}
public static void addUnknownSuppressWarningProposals(IInvocationContext context, IProblemLocation problem, Collection proposals) {
ASTNode coveringNode= context.getCoveringNode();
if (!(coveringNode instanceof StringLiteral))
return;
AST ast= coveringNode.getAST();
StringLiteral literal= (StringLiteral) coveringNode;
String literalValue= literal.getLiteralValue();
String[] allWarningTokens= CorrectionEngine.getAllWarningTokens();
for (int i= 0; i < allWarningTokens.length; i++) {
String curr= allWarningTokens[i];
if (NameMatcher.isSimilarName(literalValue, curr)) {
StringLiteral newLiteral= ast.newStringLiteral();
newLiteral.setLiteralValue(curr);
ASTRewrite rewrite= ASTRewrite.create(ast);
rewrite.replace(literal, newLiteral, null);
String label= Messages.format(CorrectionMessages.SuppressWarningsSubProcessor_fix_suppress_token_label, new String[] { curr });
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 5, image);
proposals.add(proposal);
}
}
}
}