Skip to content

Commit

Permalink
Move the logic of MissingAnnotationAttributes to o.e.j.core.manipulation
Browse files Browse the repository at this point in the history
Signed-off-by: David Thompson <davthomp@redhat.com>
  • Loading branch information
datho7561 committed Dec 6, 2022
1 parent b8bdee9 commit 77adf22
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 101 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;

import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages;
import org.eclipse.jdt.internal.ui.text.correction.IProblemLocationCore;

public class MissingAnnotationAttributesFixCore extends CompilationUnitRewriteOperationsFixCore {

public MissingAnnotationAttributesFixCore(String name, CompilationUnit compilationUnit, CompilationUnitRewriteOperation operation) {
super(name, compilationUnit, operation);
}

/**
* Returns a fix that adds the missing required attributes to the annotation at the problem
* location, or null if the given problem location isn't an annotation.
*
* @param cu the AST of the compilation unit where an attribute is missing required attributes
* @param problemLocation the error marker that marks the annotation that's missing attributes
* @return a fix that adds the missing required attributes to the annotation at the problem
* location, or null if the given problem location isn't an annotation
*/
public static MissingAnnotationAttributesFixCore addMissingAnnotationAttributesProposal(CompilationUnit cu, IProblemLocationCore problemLocation) {
ASTNode selectedNode= problemLocation.getCoveringNode(cu);
if (!(selectedNode instanceof Annotation)) {
return null;
}
Annotation annotation= (Annotation) selectedNode;
MissingAnnotationAttributesProposalOperation rewriteProposal= new MissingAnnotationAttributesProposalOperation(annotation);

return new MissingAnnotationAttributesFixCore(CorrectionMessages.MissingAnnotationAttributesProposal_add_missing_attributes_label, cu, rewriteProposal);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;

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.ArrayInitializer;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
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.ListRewrite;

import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperation;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;

public class MissingAnnotationAttributesProposalOperation extends CompilationUnitRewriteOperation {

private Annotation fAnnotation;

public MissingAnnotationAttributesProposalOperation(Annotation annotation) {
fAnnotation= annotation;
Assert.isNotNull(annotation.resolveTypeBinding());
}

@Override
public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModelCore linkedModel) throws CoreException {
ASTRewrite rewrite= cuRewrite.getASTRewrite();

AST ast= fAnnotation.getAST();

ListRewrite listRewrite;
if (fAnnotation instanceof NormalAnnotation) {
listRewrite= rewrite.getListRewrite(fAnnotation, NormalAnnotation.VALUES_PROPERTY);
} else {
NormalAnnotation newAnnotation= ast.newNormalAnnotation();
newAnnotation.setTypeName((Name) rewrite.createMoveTarget(fAnnotation.getTypeName()));
rewrite.replace(fAnnotation, newAnnotation, null);

listRewrite= rewrite.getListRewrite(newAnnotation, NormalAnnotation.VALUES_PROPERTY);
}
addMissingAtributes(fAnnotation.resolveTypeBinding(), listRewrite, cuRewrite, linkedModel);

}

private void addMissingAtributes(ITypeBinding binding, ListRewrite listRewriter, CompilationUnitRewrite cuRewrite, LinkedProposalModelCore linkedModel) {
Set<String> implementedAttribs= new HashSet<>();
if (fAnnotation instanceof NormalAnnotation) {
List<MemberValuePair> list= ((NormalAnnotation) fAnnotation).values();
for (MemberValuePair curr : list) {
implementedAttribs.add(curr.getName().getIdentifier());
}
} else if (fAnnotation instanceof SingleMemberAnnotation) {
implementedAttribs.add("value"); //$NON-NLS-1$
}
ASTRewrite rewriter= listRewriter.getASTRewrite();
AST ast= rewriter.getAST();
ImportRewriteContext context= null;
ASTNode bodyDeclaration= ASTResolving.findParentBodyDeclaration(listRewriter.getParent());
if (bodyDeclaration != null) {
context= new ContextSensitiveImportRewriteContext(bodyDeclaration, cuRewrite.getImportRewrite());
}

IMethodBinding[] declaredMethods= binding.getDeclaredMethods();
for (int i= 0; i < declaredMethods.length; i++) {
IMethodBinding curr= declaredMethods[i];
if (!implementedAttribs.contains(curr.getName()) && curr.getDefaultValue() == null) {
MemberValuePair pair= ast.newMemberValuePair();
pair.setName(ast.newSimpleName(curr.getName()));
pair.setValue(newDefaultExpression(ast, curr.getReturnType(), context, cuRewrite.getImportRewrite()));
listRewriter.insertLast(pair, null);

linkedModel.getPositionGroup("val_name_" + i, true).addPosition(rewriter.track(pair.getName()), false); //$NON-NLS-1$
linkedModel.getPositionGroup("val_type_" + i, true).addPosition(rewriter.track(pair.getValue()), false); //$NON-NLS-1$
}
}
}

private Expression newDefaultExpression(AST ast, ITypeBinding type, ImportRewriteContext context, ImportRewrite importRewrite) {
if (type.isPrimitive()) {
String name= type.getName();
if ("boolean".equals(name)) { //$NON-NLS-1$
return ast.newBooleanLiteral(false);
} else {
return ast.newNumberLiteral("0"); //$NON-NLS-1$
}
}
if (type == ast.resolveWellKnownType("java.lang.String")) { //$NON-NLS-1$
return ast.newStringLiteral();
}
if (type.isArray()) {
ArrayInitializer initializer= ast.newArrayInitializer();
initializer.expressions().add(newDefaultExpression(ast, type.getElementType(), context, importRewrite));
return initializer;
}
if (type.isAnnotation()) {
MarkerAnnotation annotation= ast.newMarkerAnnotation();
annotation.setTypeName(ast.newName(importRewrite.addImport(type, context)));
return annotation;
}
return ast.newNullLiteral();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
* Copyright (c) 2000, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -13,126 +13,36 @@
*******************************************************************************/
package org.eclipse.jdt.internal.ui.text.correction.proposals;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;

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.ArrayInitializer;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;

import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperation;
import org.eclipse.jdt.internal.corext.fix.MissingAnnotationAttributesProposalOperation;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;

import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages;

public class MissingAnnotationAttributesProposal extends LinkedCorrectionProposal {

private Annotation fAnnotation;
private CompilationUnitRewrite fCompilationUnitRewrite;

private CompilationUnitRewriteOperation fASTRewriteProposalCore;

public MissingAnnotationAttributesProposal(ICompilationUnit cu, Annotation annotation, int relevance) {
super(CorrectionMessages.MissingAnnotationAttributesProposal_add_missing_attributes_label, cu, null, relevance, null);
fASTRewriteProposalCore= new MissingAnnotationAttributesProposalOperation(annotation);
fCompilationUnitRewrite= new CompilationUnitRewrite(cu, (CompilationUnit)annotation.getRoot());
setImage(JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE));

fAnnotation= annotation;
Assert.isNotNull(fAnnotation.resolveTypeBinding());
}

@Override
protected ASTRewrite getRewrite() throws CoreException {
AST ast= fAnnotation.getAST();

ASTRewrite rewrite= ASTRewrite.create(ast);
createImportRewrite((CompilationUnit) fAnnotation.getRoot());

ListRewrite listRewrite;
if (fAnnotation instanceof NormalAnnotation) {
listRewrite= rewrite.getListRewrite(fAnnotation, NormalAnnotation.VALUES_PROPERTY);
} else {
NormalAnnotation newAnnotation= ast.newNormalAnnotation();
newAnnotation.setTypeName((Name) rewrite.createMoveTarget(fAnnotation.getTypeName()));
rewrite.replace(fAnnotation, newAnnotation, null);

listRewrite= rewrite.getListRewrite(newAnnotation, NormalAnnotation.VALUES_PROPERTY);
}
addMissingAtributes(fAnnotation.resolveTypeBinding(), listRewrite);

return rewrite;
}

private void addMissingAtributes(ITypeBinding binding, ListRewrite listRewriter) {
Set<String> implementedAttribs= new HashSet<>();
if (fAnnotation instanceof NormalAnnotation) {
List<MemberValuePair> list= ((NormalAnnotation) fAnnotation).values();
for (MemberValuePair curr : list) {
implementedAttribs.add(curr.getName().getIdentifier());
}
} else if (fAnnotation instanceof SingleMemberAnnotation){
implementedAttribs.add("value"); //$NON-NLS-1$
}
ASTRewrite rewriter= listRewriter.getASTRewrite();
AST ast= rewriter.getAST();
ImportRewriteContext context= null;
ASTNode bodyDeclaration= ASTResolving.findParentBodyDeclaration(listRewriter.getParent());
if (bodyDeclaration != null) {
context= new ContextSensitiveImportRewriteContext(bodyDeclaration, getImportRewrite());
}

IMethodBinding[] declaredMethods= binding.getDeclaredMethods();
for (int i= 0; i < declaredMethods.length; i++) {
IMethodBinding curr= declaredMethods[i];
if (!implementedAttribs.contains(curr.getName()) && curr.getDefaultValue() == null) {
MemberValuePair pair= ast.newMemberValuePair();
pair.setName(ast.newSimpleName(curr.getName()));
pair.setValue(newDefaultExpression(ast, curr.getReturnType(), context));
listRewriter.insertLast(pair, null);

addLinkedPosition(rewriter.track(pair.getName()), false, "val_name_" + i); //$NON-NLS-1$
addLinkedPosition(rewriter.track(pair.getValue()), false, "val_type_" + i); //$NON-NLS-1$
}
}
}

private Expression newDefaultExpression(AST ast, ITypeBinding type, ImportRewriteContext context) {
if (type.isPrimitive()) {
String name= type.getName();
if ("boolean".equals(name)) { //$NON-NLS-1$
return ast.newBooleanLiteral(false);
} else {
return ast.newNumberLiteral("0"); //$NON-NLS-1$
}
}
if (type == ast.resolveWellKnownType("java.lang.String")) { //$NON-NLS-1$
return ast.newStringLiteral();
}
if (type.isArray()) {
ArrayInitializer initializer= ast.newArrayInitializer();
initializer.expressions().add(newDefaultExpression(ast, type.getElementType(), context));
return initializer;
}
if (type.isAnnotation()) {
MarkerAnnotation annotation= ast.newMarkerAnnotation();
annotation.setTypeName(ast.newName(getImportRewrite().addImport(type, context)));
return annotation;
}
return ast.newNullLiteral();
fASTRewriteProposalCore.rewriteAST(fCompilationUnitRewrite, getLinkedProposalModel());
return fCompilationUnitRewrite.getASTRewrite();
}
}

0 comments on commit 77adf22

Please sign in to comment.