/*******************************************************************************
* Copyright (c) 2017 Alex Xu 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:
* Alex Xu - initial API and implementation
*******************************************************************************/
package org.eclipse.php.internal.ui.text.correction;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.compiler.problem.IProblemIdentifier;
import org.eclipse.dltk.core.Flags;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.ui.DLTKPluginImages;
import org.eclipse.php.core.ast.nodes.*;
import org.eclipse.php.internal.core.ast.rewrite.ASTRewrite;
import org.eclipse.php.internal.core.compiler.ast.parser.PHPProblemIdentifier;
import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
import org.eclipse.php.internal.ui.PHPUiPlugin;
import org.eclipse.php.internal.ui.text.correction.proposals.ASTRewriteCorrectionProposal;
import org.eclipse.php.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
import org.eclipse.php.internal.ui.util.Messages;
import org.eclipse.php.ui.editor.SharedASTProvider;
import org.eclipse.php.ui.text.correction.IInvocationContext;
import org.eclipse.php.ui.text.correction.IProblemLocation;
import org.eclipse.swt.graphics.Image;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class ModifierCorrectionSubProcessor {
public static final int TO_STATIC = 1;
public static final int TO_VISIBLE = 2;
public static final int TO_NON_PRIVATE = 3;
public static final int TO_NON_STATIC = 4;
public static final int TO_NON_FINAL = 5;
public static void addNonAccessibleReferenceProposal(IInvocationContext context, IProblemLocation problem,
Collection proposals, int kind, int relevance) throws CoreException {
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
IBinding binding = null;
switch (selectedNode.getType()) {
case ASTNode.IDENTIFIER:
binding = ((Identifier) selectedNode).resolveBinding();
break;
case ASTNode.NAMESPACE_NAME:
List<Identifier> segments = ((NamespaceName) selectedNode).segments();
if (segments.size() > 0) {
binding = segments.get(segments.size() - 1).resolveBinding();
}
break;
default:
return;
}
ITypeBinding typeBinding = null;
String name;
if (binding instanceof ITypeBinding) {
typeBinding = (ITypeBinding) binding;
name = PHPModelUtils.extractElementName(binding.getName());
} else {
return;
}
if (typeBinding != null) {
int excludedModifiers = 0;
String label;
switch (kind) {
case TO_NON_FINAL:
label = Messages.format(
CorrectionMessages.ModifierCorrectionSubProcessor_changemodifiertononfinal_description, name);
excludedModifiers = ClassDeclaration.MODIFIER_FINAL;
break;
default:
throw new IllegalArgumentException("not supported"); //$NON-NLS-1$
}
IType type = (IType) typeBinding.getPHPElement();
ISourceModule targetCU = type.getSourceModule();
if (targetCU != null) {
try {
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
Program root = SharedASTProvider.getAST(targetCU, SharedASTProvider.WAIT_YES, null);
if (root != null) {
AST ast = root.getAST();
ASTRewrite rewrite = ASTRewrite.create(ast);
ClassDeclaration decl = (ClassDeclaration) root.findDeclaringNode(typeBinding);
rewrite.set(decl, ClassDeclaration.MODIFIER_PROPERTY, decl.getModifier() & ~excludedModifiers,
null);
ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, targetCU,
rewrite, 6, image);
proposals.add(proposal);
}
} catch (IOException e) {
PHPUiPlugin.log(e);
}
}
}
}
public static void addMethodRequiresBodyProposals(IInvocationContext context, IProblemLocation problem,
Collection proposals) {
ISourceModule cu = context.getCompilationUnit();
AST ast = context.getASTRoot().getAST();
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (!(selectedNode.getParent() instanceof FunctionDeclaration)) {
return;
}
selectedNode = selectedNode.getParent();
FunctionDeclaration decl = (FunctionDeclaration) selectedNode;
MethodDeclaration mdecl = (MethodDeclaration) decl.getParent();
{
ASTRewrite rewrite = ASTRewrite.create(ast);
Block body = ast.newBlock();
rewrite.set(decl, FunctionDeclaration.BODY_PROPERTY, body, null);
String label = CorrectionMessages.ModifierCorrectionSubProcessor_addmissingbody_description;
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, cu, rewrite, 9, image);
proposals.add(proposal);
}
if (!Flags.isAbstract(mdecl.getModifier())) {
ASTRewrite rewrite = ASTRewrite.create(ast);
rewrite.set(mdecl, MethodDeclaration.MODIFIER_PROPERTY, mdecl.getModifier() | Modifiers.AccAbstract, null);
String label = CorrectionMessages.ModifierCorrectionSubProcessor_setmethodabstract_description;
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, cu, rewrite, 8, image);
proposals.add(proposal);
}
}
public static void addAbstractMethodProposals(IInvocationContext context, IProblemLocation problem,
Collection proposals) {
ISourceModule cu = context.getCompilationUnit();
Program astRoot = context.getASTRoot();
ASTNode selectedNode = problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
FunctionDeclaration funcDecl = null;
while ((selectedNode = selectedNode.getParent()) != null) {
if (selectedNode instanceof FunctionDeclaration) {
funcDecl = (FunctionDeclaration) selectedNode;
break;
}
}
if (funcDecl == null) {
return;
}
MethodDeclaration mdecl = (MethodDeclaration) funcDecl.getParent();
ASTNode parent = funcDecl;
ClassDeclaration parentTypeDecl = null;
boolean parentIsAbstractClass = false;
while ((parent = parent.getParent()) != null) {
if (parent instanceof ClassDeclaration) {
parentTypeDecl = (ClassDeclaration) parent;
if (Flags.isAbstract(parentTypeDecl.getModifier())) {
parentIsAbstractClass = true;
}
break;
} else if (parent instanceof AnonymousClassDeclaration) {
parentIsAbstractClass = false;
break;
}
}
boolean hasNoBody = funcDecl.getBody() == null;
IProblemIdentifier id = problem.getProblemIdentifier();
if (id == PHPProblemIdentifier.AbstractMethodInAbstractClass || parentIsAbstractClass) {
AST ast = astRoot.getAST();
ASTRewrite rewrite = ASTRewrite.create(ast);
rewrite.set(mdecl, MethodDeclaration.MODIFIER_PROPERTY, mdecl.getModifier() & ~Modifiers.AccAbstract, null);
if (hasNoBody) {
Block body = ast.newBlock();
rewrite.set(funcDecl, FunctionDeclaration.BODY_PROPERTY, body, null);
}
String label = CorrectionMessages.ModifierCorrectionSubProcessor_removeabstract_description;
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, cu, rewrite, 6, image);
proposals.add(proposal);
}
if (!hasNoBody && id == PHPProblemIdentifier.BodyForAbstractMethod) {
ASTRewrite rewrite = ASTRewrite.create(funcDecl.getAST());
rewrite.remove(funcDecl.getBody(), null);
String label = CorrectionMessages.ModifierCorrectionSubProcessor_removebody_description;
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal2 = new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image);
proposals.add(proposal2);
}
if (id == PHPProblemIdentifier.AbstractMethodInAbstractClass && parentTypeDecl != null
&& !(parentTypeDecl instanceof TraitDeclaration)) {
addMakeTypeAbstractProposal(context, parentTypeDecl, proposals, cu);
}
}
public static void addAbstractTypeProposals(IInvocationContext context, IProblemLocation problem,
Collection proposals) {
Program astRoot = context.getASTRoot();
ASTNode selectedNode = problem.getCoveringNode(astRoot);
if (selectedNode == null) {
return;
}
ClassDeclaration parentTypeDecl = null;
if (selectedNode instanceof Identifier) {
ASTNode parent = selectedNode.getParent();
if (parent != null) {
parentTypeDecl = (ClassDeclaration) parent;
}
} else if (selectedNode instanceof ClassDeclaration) {
parentTypeDecl = (ClassDeclaration) selectedNode;
}
if (parentTypeDecl == null) {
return;
}
addMakeTypeAbstractProposal(context, parentTypeDecl, proposals, context.getCompilationUnit());
}
public static void addMakeTypeAbstractProposal(IInvocationContext context, ClassDeclaration parentTypeDecl,
Collection proposals, ISourceModule cu) {
ASTRewrite rewrite = ASTRewrite.create(parentTypeDecl.getAST());
rewrite.set(parentTypeDecl, ClassDeclaration.MODIFIER_PROPERTY,
parentTypeDecl.getModifier() | Modifiers.AccAbstract, null);
String label = Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_addabstract_description,
parentTypeDecl.getName().getName());
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image);
proposals.add(proposal);
}
}