content: /*******************************************************************************
   * Copyright (c) 2000, 2009 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.wst.jsdt.internal.ui.text.correction;
  
  import java.util.HashSet;
  
  import org.eclipse.wst.jsdt.core.CompletionProposal;
  import org.eclipse.wst.jsdt.core.CompletionRequestor;
  import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  import org.eclipse.wst.jsdt.core.Signature;
  import org.eclipse.wst.jsdt.core.dom.ASTNode;
  import org.eclipse.wst.jsdt.core.dom.JSdoc;
  import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
  import org.eclipse.wst.jsdt.core.dom.Name;
  import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
  import org.eclipse.wst.jsdt.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;
  	public static final int REF_TYPES_AND_VAR= REF_TYPES | VARIABLES;
  	public static final int ALL_TYPES= PRIMITIVETYPES | REF_TYPES_AND_VAR;
  
  	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(IJavaScriptUnit cu, Name name, int kind) throws JavaScriptModelException {
  		int pos= name.getStartPosition();
  		int nArguments= -1;
  
  		String identifier= ASTNodes.getSimpleNameIdentifier(name);
  		String returnType= null;
  		IJavaScriptUnit preparedCU= null;
  
  		try {
  //			if (name.isQualifiedName()) {
  //				pos= ((QualifiedName) name).getName().getStartPosition();
  //			} else {
  				pos= name.getStartPosition() + 1; // first letter must be included, other
  		//	}
  			JSdoc javadoc=  (JSdoc) ASTNodes.getParent(name, ASTNode.JSDOC);
  			if (javadoc != null) {
  				preparedCU= createPreparedCU(cu, javadoc, name.getStartPosition());
  				cu= preparedCU;
  			}
  
  			SimilarElementsRequestor requestor= new SimilarElementsRequestor(identifier, kind, nArguments, returnType);
  			/* ORIGINAL -------- BC */
  			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);
  			
  //			
  //
  //			requestor.setIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF, false);
  //			requestor.setIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, false);
  //			requestor.setIgnored(CompletionProposal.FIELD_REF, false);
  //			requestor.setIgnored(CompletionProposal.KEYWORD, false);
  //			requestor.setIgnored(CompletionProposal.LABEL_REF, false);
  //			requestor.setIgnored(CompletionProposal.LOCAL_VARIABLE_REF, false);
  //			requestor.setIgnored(CompletionProposal.METHOD_DECLARATION, false);
  //			requestor.setIgnored(CompletionProposal.METHOD_NAME_REFERENCE, false);
  //			requestor.setIgnored(CompletionProposal.METHOD_REF, false);
  //			requestor.setIgnored(CompletionProposal.PACKAGE_REF, false);
  //			requestor.setIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION, false);
  //			requestor.setIgnored(CompletionProposal.VARIABLE_DECLARATION, false);
  //			
  //			requestor.setIgnored(CompletionProposal.JSDOC_BLOCK_TAG, true);
  //			requestor.setIgnored(CompletionProposal.JSDOC_FIELD_REF, true);
  //			requestor.setIgnored(CompletionProposal.JSDOC_INLINE_TAG, true);
  //			requestor.setIgnored(CompletionProposal.JSDOC_METHOD_REF, true);
  //			requestor.setIgnored(CompletionProposal.JSDOC_PARAM_REF, true);
  //			requestor.setIgnored(CompletionProposal.JSDOC_TYPE_REF, true);
  //			requestor.setIgnored(CompletionProposal.JSDOC_VALUE_REF, true);
  //			
  //			requestor.setIgnored(CompletionProposal.TYPE_REF, true);
  //			
  			
  			
  			
  			
  			return requestor.process(cu, pos);
  		} finally {
  			if (preparedCU != null) {
  				preparedCU.discardWorkingCopy();
  			}
  		}
  	}
  
  	private static IJavaScriptUnit createPreparedCU(IJavaScriptUnit cu, JSdoc comment, int wordStart) throws JavaScriptModelException {
  		int startpos= comment.getStartPosition();
  		boolean isTopLevel= comment.getParent().getParent() instanceof JavaScriptUnit;
  		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.
  		 */
  		IJavaScriptUnit 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(IJavaScriptUnit cu, int pos) throws JavaScriptModelException {
  		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) {
  		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(typeNameSig));
  		if (TypeFilter.isFiltered(fullName)) {
  			return;
  		}
  		if (NameMatcher.isSimilarName(fName, Signature.getSimpleName(fullName))) {
  			addResult(new SimilarElement(kind, fullName, relevance));
  		}
  	}
  
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.core.CompletionRequestor#accept(org.eclipse.wst.jsdt.core.CompletionProposal)
  	 */
  	public void accept(CompletionProposal proposal) {
  		if (proposal.getKind() == CompletionProposal.TYPE_REF) {
  			addType(proposal.getSignature(), proposal.getFlags(), proposal.getRelevance());
  		}
  	}
  }
  