/*******************************************************************************
* 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.util.Collection;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.internal.corext.util.QualifiedTypeNameHistory;
import org.eclipse.dltk.ui.DLTKPluginImages;
import org.eclipse.dltk.ui.viewsupport.BasicElementLabels;
import org.eclipse.php.core.ast.nodes.*;
import org.eclipse.php.internal.core.ast.rewrite.ASTRewrite;
import org.eclipse.php.internal.core.ast.rewrite.ImportRewrite;
import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
import org.eclipse.php.internal.ui.text.correction.proposals.ASTRewriteCorrectionProposal;
import org.eclipse.php.internal.ui.text.correction.proposals.AbstractCorrectionProposal;
import org.eclipse.php.internal.ui.text.correction.proposals.AddImportCorrectionProposal;
import org.eclipse.php.internal.ui.text.correction.proposals.CUCorrectionProposal;
import org.eclipse.php.internal.ui.util.Messages;
import org.eclipse.php.ui.text.correction.IInvocationContext;
import org.eclipse.php.ui.text.correction.IProblemLocation;
import org.eclipse.swt.graphics.Image;
public class UnresolvedElementsSubProcessor {
public static void getTypeProposals(IInvocationContext context, IProblemLocation problem,
Collection<AbstractCorrectionProposal> proposals) throws CoreException {
ISourceModule cu = context.getCompilationUnit();
ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
return;
}
while (selectedNode.getLocationInParent() == Identifier.NAME_PROPERTY) {
selectedNode = selectedNode.getParent();
}
Identifier node = null;
if (selectedNode instanceof Identifier) {
node = ((Identifier) selectedNode);
} else if (selectedNode instanceof Comment) {
int start = problem.getOffset();
int end = problem.getOffset() + problem.getLength();
String nodeName = cu.getSource().substring(start, end);
node = new Identifier(start, end, context.getASTRoot().getAST(), nodeName);
node.setParent(selectedNode, Comment.COMMENT_TYPE_PROPERTY);
selectedNode = node;
} else {
return;
}
int kind = evauateTypeKind(selectedNode);
addSimilarTypeProposals(kind, cu, node, 3, proposals);
}
private static void addSimilarTypeProposals(int kind, ISourceModule cu, Identifier node, int relevance,
Collection<AbstractCorrectionProposal> proposals) throws CoreException {
SimilarElement[] elements = SimilarElementsRequestor.findSimilarElement(cu, node, kind);
// add all similar elements
for (int i = 0; i < elements.length; i++) {
SimilarElement elem = elements[i];
if ((elem.getKind() & SimilarElementsRequestor.ALL_TYPES) != 0) {
String fullName = elem.getName();
proposals.add(createTypeRefChangeProposal(cu, fullName, node, relevance, elements.length));
}
}
}
private static CUCorrectionProposal createTypeRefChangeProposal(ISourceModule cu, String fullName, Identifier node,
int relevance, int maxProposals) {
ImportRewrite importRewrite = null;
String packName = PHPModelUtils.extractNameSpaceName(fullName);
if (packName == null) {
packName = "global namespace"; //$NON-NLS-1$
} else if (packName.endsWith(SimilarElementsRequestor.ENCLOSING_TYPE_SEPARATOR)) {
packName = packName.substring(0, packName.length() - 1);
}
// variables
Program root = (Program) node.getRoot();
NamespaceDeclaration namespace = root.getNamespaceDeclaration(node.getStart());
importRewrite = ImportRewrite.create((Program) node.getRoot(), true);
String simpleName = importRewrite.addImport(namespace, fullName);
if (simpleName == null)
return null;
if (!isLikelyTypeName(simpleName)) {
relevance -= 2;
}
ASTRewriteCorrectionProposal proposal;
if (importRewrite != null && simpleName.equals(((Identifier) node).getName())) {
String[] arg = { simpleName, packName };
String label = Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_importtype_description,
arg);
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_OBJS_IMPDECL);
int boost = QualifiedTypeNameHistory.getBoost(fullName, 0, maxProposals);
proposal = new AddImportCorrectionProposal(label, cu, relevance + 100 + boost, image, packName, simpleName,
(Identifier) node);
} else {
String[] arg = { BasicElementLabels.getJavaElementName(simpleName),
BasicElementLabels.getJavaElementName(packName) };
String label = Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changetype_description,
arg);
ASTRewrite rewrite = ASTRewrite.create(node.getAST());
rewrite.replace(node, rewrite.createStringPlaceholder(simpleName, ASTNode.IDENTIFIER), null);
Image image = DLTKPluginImages.get(DLTKPluginImages.IMG_CORRECTION_CHANGE);
proposal = new ASTRewriteCorrectionProposal(label, cu, rewrite, relevance, image);
}
if (importRewrite != null) {
proposal.setImportRewrite(importRewrite);
}
return proposal;
}
private static boolean isLikelyTypeName(String name) {
return name.length() > 0 && Character.isUpperCase(name.charAt(0));
}
private static int evauateTypeKind(ASTNode node) {
int kind = ASTResolving.getPossibleTypeKinds(node);
return kind;
}
}