blob: d1d703dbf6ff78fec4ee8fde546e5316f783b7c8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.HashSet;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.CompletionRequestor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.util.TypeFilter;
public class SimilarElementsRequestor extends CompletionRequestor {
public static final int CLASSES= 1 << 1;
public static final int INTERFACES= 1 << 2;
public static final int ANNOTATIONS= 1 << 3;
public static final int ENUMS= 1 << 4;
public static final int VARIABLES= 1 << 5;
public static final int PRIMITIVETYPES= 1 << 6;
public static final int VOIDTYPE= 1 << 7;
public static final int REF_TYPES= CLASSES | INTERFACES | ENUMS | ANNOTATIONS | VARIABLES;
public static final int ALL_TYPES= PRIMITIVETYPES | REF_TYPES;
private static final String[] PRIM_TYPES= { "boolean", "byte", "char", "short", "int", "long", "float", "double" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
private int fKind;
private String fName;
private HashSet fResult;
public static SimilarElement[] findSimilarElement(ICompilationUnit cu, Name name, int kind) throws JavaModelException {
int pos= name.getStartPosition();
int nArguments= -1;
String identifier= ASTNodes.getSimpleNameIdentifier(name);
String returnType= null;
ICompilationUnit preparedCU= null;
try {
if (name.isQualifiedName()) {
pos= ((QualifiedName) name).getName().getStartPosition();
} else {
pos= name.getStartPosition() + 1; // first letter must be included, other
}
Javadoc javadoc= (Javadoc) ASTNodes.getParent(name, ASTNode.JAVADOC);
if (javadoc != null) {
preparedCU= createPreparedCU(cu, javadoc, name.getStartPosition());
cu= preparedCU;
}
SimilarElementsRequestor requestor= new SimilarElementsRequestor(identifier, kind, nArguments, returnType);
requestor.setIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, true);
requestor.setIgnored(CompletionProposal.KEYWORD, true);
requestor.setIgnored(CompletionProposal.LABEL_REF, true);
requestor.setIgnored(CompletionProposal.METHOD_DECLARATION, true);
requestor.setIgnored(CompletionProposal.PACKAGE_REF, true);
requestor.setIgnored(CompletionProposal.VARIABLE_DECLARATION, true);
requestor.setIgnored(CompletionProposal.METHOD_REF, true);
requestor.setIgnored(CompletionProposal.FIELD_REF, true);
requestor.setIgnored(CompletionProposal.LOCAL_VARIABLE_REF, true);
requestor.setIgnored(CompletionProposal.VARIABLE_DECLARATION, true);
requestor.setIgnored(CompletionProposal.VARIABLE_DECLARATION, true);
requestor.setIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION, true);
requestor.setIgnored(CompletionProposal.METHOD_NAME_REFERENCE, true);
return requestor.process(cu, pos);
} finally {
if (preparedCU != null) {
preparedCU.discardWorkingCopy();
}
}
}
private static ICompilationUnit createPreparedCU(ICompilationUnit cu, Javadoc comment, int wordStart) throws JavaModelException {
int startpos= comment.getStartPosition();
boolean isTopLevel= comment.getParent().getParent() instanceof CompilationUnit;
char[] content= (char[]) cu.getBuffer().getCharacters().clone();
if (isTopLevel && (wordStart + 6 < content.length)) {
content[startpos++]= 'i'; content[startpos++]= 'm'; content[startpos++]= 'p';
content[startpos++]= 'o'; content[startpos++]= 'r'; content[startpos++]= 't';
}
if (wordStart < content.length) {
for (int i= startpos; i < wordStart; i++) {
content[i]= ' ';
}
}
/*
* Explicitly create a new non-shared working copy.
*/
ICompilationUnit newCU= cu.getWorkingCopy(null);
newCU.getBuffer().setContents(content);
return newCU;
}
/**
* Constructor for SimilarElementsRequestor.
*/
private SimilarElementsRequestor(String name, int kind, int nArguments, String preferredType) {
super();
fName= name;
fKind= kind;
fResult= new HashSet();
}
private void addResult(SimilarElement elem) {
fResult.add(elem);
}
private SimilarElement[] process(ICompilationUnit cu, int pos) throws JavaModelException {
try {
cu.codeComplete(pos, this);
processKeywords();
return (SimilarElement[]) fResult.toArray(new SimilarElement[fResult.size()]);
} finally {
fResult.clear();
}
}
private boolean isKind(int kind) {
return (fKind & kind) != 0;
}
/**
* Method addPrimitiveTypes.
*/
private void processKeywords() {
if (isKind(PRIMITIVETYPES)) {
for (int i= 0; i < PRIM_TYPES.length; i++) {
if (NameMatcher.isSimilarName(fName, PRIM_TYPES[i])) {
addResult(new SimilarElement(PRIMITIVETYPES, PRIM_TYPES[i], 50));
}
}
}
if (isKind(VOIDTYPE)) {
String voidType= "void"; //$NON-NLS-1$
if (NameMatcher.isSimilarName(fName, voidType)) {
addResult(new SimilarElement(PRIMITIVETYPES, voidType, 50));
}
}
}
private static final int getKind(int flags, char[] typeNameSig) {
if (Signature.getTypeSignatureKind(typeNameSig) == Signature.TYPE_VARIABLE_SIGNATURE) {
return VARIABLES;
}
if (Flags.isAnnotation(flags)) {
return ANNOTATIONS;
}
if (Flags.isInterface(flags)) {
return INTERFACES;
}
if (Flags.isEnum(flags)) {
return ENUMS;
}
return CLASSES;
}
private void addType(char[] typeNameSig, int flags, int relevance) {
int kind= getKind(flags, typeNameSig);
if (!isKind(kind)) {
return;
}
String fullName= new String(Signature.toCharArray(Signature.getTypeErasure(typeNameSig)));
if (TypeFilter.isFiltered(fullName)) {
return;
}
if (NameMatcher.isSimilarName(fName, Signature.getSimpleName(fullName))) {
addResult(new SimilarElement(kind, fullName, relevance));
}
}
/* (non-Javadoc)
* @see org.eclipse.jdt.core.CompletionRequestor#accept(org.eclipse.jdt.core.CompletionProposal)
*/
public void accept(CompletionProposal proposal) {
if (proposal.getKind() == CompletionProposal.TYPE_REF) {
addType(proposal.getSignature(), proposal.getFlags(), proposal.getRelevance());
}
}
}