/******************************************************************************* * Copyright (c) 2000, 2008 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.corext.codemanipulation; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.wst.jsdt.core.IJavaScriptElement; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration; import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit; import org.eclipse.wst.jsdt.core.dom.IBinding; import org.eclipse.wst.jsdt.core.dom.ITypeBinding; import org.eclipse.wst.jsdt.core.dom.Modifier; import org.eclipse.wst.jsdt.core.dom.Name; import org.eclipse.wst.jsdt.core.dom.rewrite.ImportRewrite; import org.eclipse.wst.jsdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; import org.eclipse.wst.jsdt.internal.corext.dom.ScopeAnalyzer; import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil; /** * * Provisional API: This class/interface is part of an interim API that is still under development and expected to * change significantly before reaching stability. It is being made available at this early stage to solicit feedback * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken * (repeatedly) as the API evolves. */ public class ContextSensitiveImportRewriteContext extends ImportRewriteContext { private final JavaScriptUnit fCompilationUnit; private final int fPosition; private IBinding[] fDeclarationsInScope; private Name[] fImportedNames; private final ImportRewrite fImportRewrite; public ContextSensitiveImportRewriteContext(JavaScriptUnit compilationUnit, int position, ImportRewrite importRewrite) { fCompilationUnit= compilationUnit; fPosition= position; fImportRewrite= importRewrite; fDeclarationsInScope= null; fImportedNames= null; } public int findInContext(String qualifier, String name, int kind) { int defaultResult= fImportRewrite.getDefaultImportRewriteContext().findInContext(qualifier, name, kind); if (defaultResult != ImportRewriteContext.RES_NAME_UNKNOWN) return defaultResult; if (fImportRewrite.isImportMatchesType()) { IBinding[] declarationsInScope = getDeclarationsInScope(); for (int i = 0; i < declarationsInScope.length; i++) { if (declarationsInScope[i] instanceof ITypeBinding) { ITypeBinding typeBinding = (ITypeBinding) declarationsInScope[i]; if (isSameType(typeBinding, qualifier, name)) { return RES_NAME_FOUND; } else if (isConflicting(typeBinding, name)) { return RES_NAME_CONFLICT; } } else if (declarationsInScope[i] != null) { if (isConflicting(declarationsInScope[i], name)) { return RES_NAME_CONFLICT; } } } Name[] names = getImportedNames(); for (int i = 0; i < names.length; i++) { IBinding binding = names[i].resolveBinding(); if (binding instanceof ITypeBinding) { ITypeBinding typeBinding = (ITypeBinding) binding; if (isConflictingType(typeBinding, qualifier, name)) { return RES_NAME_CONFLICT; } } } List list = fCompilationUnit.types(); for (Iterator iter = list.iterator(); iter.hasNext();) { AbstractTypeDeclaration type = (AbstractTypeDeclaration) iter .next(); ITypeBinding binding = type.resolveBinding(); if (binding != null) { if (isSameType(binding, qualifier, name)) { return RES_NAME_FOUND; } else { ITypeBinding decl = containingDeclaration(binding, qualifier, name); while (decl != null && !decl.equals(binding)) { int modifiers = decl.getModifiers(); if (Modifier.isPrivate(modifiers)) return RES_NAME_CONFLICT; decl = decl.getDeclaringClass(); } } } } } String[] addedImports= fImportRewrite.getAddedImports(); String qualifiedName= JavaModelUtil.concatenateName(qualifier, name); for (int i= 0; i < addedImports.length; i++) { String addedImport= addedImports[i]; if (qualifiedName.equals(addedImport)) { return RES_NAME_FOUND; } else { if (isConflicting(name, addedImport)) return RES_NAME_CONFLICT; } } // if (qualifier.equals("java.lang")) { //$NON-NLS-1$ // //No explicit import statement required // IJavaScriptElement parent= fCompilationUnit.getJavaElement().getParent(); // if (parent instanceof IPackageFragment) { // IPackageFragment packageFragment= (IPackageFragment)parent; // try { // IJavaScriptUnit[] compilationUnits= packageFragment.getCompilationUnits(); // for (int i= 0; i < compilationUnits.length; i++) { // IJavaScriptUnit cu= compilationUnits[i]; // IType[] allTypes= cu.getAllTypes(); // for (int j= 0; j < allTypes.length; j++) { // IType type= allTypes[j]; // String packageTypeName= type.getFullyQualifiedName(); // if (isConflicting(name, packageTypeName)) // return RES_NAME_CONFLICT; // } // } // } catch (JavaScriptModelException e) { // } // } // } return RES_NAME_UNKNOWN; } private boolean isConflicting(String name, String importt) { int index= importt.lastIndexOf('.'); String importedName; if (index == -1) { importedName= importt; } else { importedName= importt.substring(index + 1, importt.length()); } if (importedName.equals(name)) { return true; } return false; } private ITypeBinding containingDeclaration(ITypeBinding binding, String qualifier, String name) { ITypeBinding[] declaredTypes= binding.getDeclaredTypes(); for (int i= 0; i < declaredTypes.length; i++) { ITypeBinding childBinding= declaredTypes[i]; if (isSameType(childBinding, qualifier, name)) { return childBinding; } else { ITypeBinding result= containingDeclaration(childBinding, qualifier, name); if (result != null) { return result; } } } return null; } private boolean isConflicting(IBinding binding, String name) { return binding.getName().equals(name); } private boolean isSameType(ITypeBinding binding, String qualifier, String name) { String qualifiedName= JavaModelUtil.concatenateName(qualifier, name); return binding.getQualifiedName().equals(qualifiedName); } private boolean isConflictingType(ITypeBinding binding, String qualifier, String name) { binding= binding.getTypeDeclaration(); return !isSameType(binding, qualifier, name) && isConflicting(binding, name); } private IBinding[] getDeclarationsInScope() { if (fDeclarationsInScope == null) { ScopeAnalyzer analyzer= new ScopeAnalyzer(fCompilationUnit); fDeclarationsInScope= analyzer.getDeclarationsInScope(fPosition, ScopeAnalyzer.METHODS | ScopeAnalyzer.TYPES | ScopeAnalyzer.VARIABLES); } return fDeclarationsInScope; } private Name[] getImportedNames() { if (fImportedNames == null) { IJavaScriptProject project= null; IJavaScriptElement javaElement= fCompilationUnit.getJavaElement(); if (javaElement != null) project= javaElement.getJavaScriptProject(); List imports= new ArrayList(); ImportReferencesCollector.collect(fCompilationUnit, project, null, imports, null); fImportedNames= (Name[])imports.toArray(new Name[imports.size()]); } return fImportedNames; } }