1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.codemanipulation;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
17 import org.eclipse.core.runtime.Assert;
19 import org.eclipse.jdt.core.CompletionProposal;
20 import org.eclipse.jdt.core.ICompilationUnit;
21 import org.eclipse.jdt.core.IJavaElement;
22 import org.eclipse.jdt.core.IJavaProject;
23 import org.eclipse.jdt.core.IPackageFragment;
24 import org.eclipse.jdt.core.IType;
25 import org.eclipse.jdt.core.ITypeRoot;
26 import org.eclipse.jdt.core.JavaModelException;
27 import org.eclipse.jdt.core.Signature;
28 import org.eclipse.jdt.core.dom.ASTNode;
29 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
30 import org.eclipse.jdt.core.dom.CompilationUnit;
31 import org.eclipse.jdt.core.dom.IBinding;
32 import org.eclipse.jdt.core.dom.ITypeBinding;
33 import org.eclipse.jdt.core.dom.Modifier;
34 import org.eclipse.jdt.core.dom.Name;
35 import org.eclipse.jdt.core.dom.SimpleName;
36 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
37 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
39 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
40 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
42 import org.eclipse.jdt.internal.ui.text.java.ImportCompletionProposal;
45 * This <code>ImportRewriteContext</code> is aware of all the types visible in
46 * <code>compilationUnit</code> at <code>position</code>.
48 * <b>Note:</b> This context only works if the AST was created with bindings!
51 public class ContextSensitiveImportRewriteContext extends ImportRewriteContext {
53 private final CompilationUnit fCompilationUnit;
54 private final int fPosition;
55 private IBinding[] fDeclarationsInScope;
56 private Name[] fImportedNames;
57 private final ImportRewrite fImportRewrite;
60 * Creates an import rewrite context at the given node's start position.
62 * @param node the node to use as context
63 * @param importRewrite the import rewrite
67 public ContextSensitiveImportRewriteContext(ASTNode node, ImportRewrite importRewrite) {
68 this((CompilationUnit)node.getRoot(), node.getStartPosition(), importRewrite);
72 * Creates an import rewrite context at the given start position.
74 * @param compilationUnit the root
75 * @param position the context position
76 * @param importRewrite the import rewrite
78 public ContextSensitiveImportRewriteContext(CompilationUnit compilationUnit, int position, ImportRewrite importRewrite) {
79 fCompilationUnit= compilationUnit;
81 fImportRewrite= importRewrite;
82 fDeclarationsInScope= null;
87 public int findInContext(String qualifier, String name, int kind) {
88 IBinding[] declarationsInScope= getDeclarationsInScope();
89 for (int i= 0; i < declarationsInScope.length; i++) {
90 if (declarationsInScope[i] instanceof ITypeBinding) {
91 ITypeBinding typeBinding= (ITypeBinding)declarationsInScope[i];
92 if (isSameType(typeBinding, qualifier, name)) {
93 return RES_NAME_FOUND;
94 } else if (isConflicting(typeBinding, name)) {
95 return RES_NAME_CONFLICT;
97 } else if (declarationsInScope[i] != null) {
98 if (isConflicting(declarationsInScope[i], name)) {
99 return RES_NAME_CONFLICT;
105 Name[] names= getImportedNames();
106 for (int i= 0; i < names.length; i++) {
107 IBinding binding= names[i].resolveBinding();
108 if (binding instanceof ITypeBinding && !binding.isRecovered()) {
109 ITypeBinding typeBinding= (ITypeBinding)binding;
110 if (isConflictingType(typeBinding, qualifier, name)) {
111 return RES_NAME_CONFLICT;
116 List<AbstractTypeDeclaration> list= fCompilationUnit.types();
117 for (Iterator<AbstractTypeDeclaration> iter= list.iterator(); iter.hasNext();) {
118 AbstractTypeDeclaration type= iter.next();
119 ITypeBinding binding= type.resolveBinding();
120 if (binding != null) {
121 if (isSameType(binding, qualifier, name)) {
122 return RES_NAME_FOUND;
124 ITypeBinding decl= containingDeclaration(binding, qualifier, name);
125 while (decl != null && !decl.equals(binding)) {
126 int modifiers= decl.getModifiers();
127 if (Modifier.isPrivate(modifiers))
128 return RES_NAME_CONFLICT;
129 decl= decl.getDeclaringClass();
135 String[] addedImports= fImportRewrite.getAddedImports();
136 String qualifiedName= JavaModelUtil.concatenateName(qualifier, name);
137 for (int i= 0; i < addedImports.length; i++) {
138 String addedImport= addedImports[i];
139 if (qualifiedName.equals(addedImport)) {
140 return RES_NAME_FOUND;
142 if (isConflicting(name, addedImport))
143 return RES_NAME_CONFLICT;
147 if (qualifier.equals("java.lang")) { //$NON-NLS-1$
148 //No explicit import statement required
149 ITypeRoot typeRoot= fCompilationUnit.getTypeRoot();
150 if (typeRoot != null) {
151 IPackageFragment packageFragment= (IPackageFragment) typeRoot.getParent();
153 ICompilationUnit[] compilationUnits= packageFragment.getCompilationUnits();
154 for (int i= 0; i < compilationUnits.length; i++) {
155 ICompilationUnit cu= compilationUnits[i];
156 IType[] allTypes= cu.getAllTypes();
157 for (int j= 0; j < allTypes.length; j++) {
158 IType type= allTypes[j];
159 String packageTypeName= type.getFullyQualifiedName();
160 if (isConflicting(name, packageTypeName))
161 return RES_NAME_CONFLICT;
164 } catch (JavaModelException e) {
169 return fImportRewrite.getDefaultImportRewriteContext().findInContext(qualifier, name, kind);
172 private boolean isConflicting(String name, String importt) {
173 int index= importt.lastIndexOf('.');
176 importedName= importt;
178 importedName= importt.substring(index + 1, importt.length());
180 if (importedName.equals(name)) {
186 private ITypeBinding containingDeclaration(ITypeBinding binding, String qualifier, String name) {
187 ITypeBinding[] declaredTypes= binding.getDeclaredTypes();
188 for (int i= 0; i < declaredTypes.length; i++) {
189 ITypeBinding childBinding= declaredTypes[i];
190 if (isSameType(childBinding, qualifier, name)) {
193 ITypeBinding result= containingDeclaration(childBinding, qualifier, name);
194 if (result != null) {
202 private boolean isConflicting(IBinding binding, String name) {
203 return binding.getName().equals(name);
206 private boolean isSameType(ITypeBinding binding, String qualifier, String name) {
207 String qualifiedName= JavaModelUtil.concatenateName(qualifier, name);
208 return binding.getQualifiedName().equals(qualifiedName);
211 private boolean isConflictingType(ITypeBinding binding, String qualifier, String name) {
212 binding= binding.getTypeDeclaration();
213 return !isSameType(binding, qualifier, name) && isConflicting(binding, name);
216 private IBinding[] getDeclarationsInScope() {
217 if (fDeclarationsInScope == null) {
218 ScopeAnalyzer analyzer= new ScopeAnalyzer(fCompilationUnit);
219 fDeclarationsInScope= analyzer.getDeclarationsInScope(fPosition, ScopeAnalyzer.METHODS | ScopeAnalyzer.TYPES | ScopeAnalyzer.VARIABLES);
221 return fDeclarationsInScope;
224 private Name[] getImportedNames() {
225 if (fImportedNames == null) {
226 IJavaProject project= null;
227 IJavaElement javaElement= fCompilationUnit.getJavaElement();
228 if (javaElement != null)
229 project= javaElement.getJavaProject();
231 List<SimpleName> imports= new ArrayList<SimpleName>();
232 ImportReferencesCollector.collect(fCompilationUnit, project, null, imports, null);
233 fImportedNames= imports.toArray(new Name[imports.size()]);
235 return fImportedNames;
238 public String generated_8668835590076207332(ImportCompletionProposal importcompletionproposal, int proposalKind, String qualifiedTypeName, char[] qualifiedType) {
239 if (proposalKind == CompletionProposal.TYPE_IMPORT) {
240 qualifiedType= importcompletionproposal.fProposal.getSignature();
241 qualifiedTypeName= String.valueOf(Signature.toCharArray(qualifiedType));
242 } else if (proposalKind == CompletionProposal.METHOD_IMPORT || proposalKind == CompletionProposal.FIELD_IMPORT) {
243 qualifiedType= Signature.getTypeErasure(importcompletionproposal.fProposal.getDeclarationSignature());
244 qualifiedTypeName= String.valueOf(Signature.toCharArray(qualifiedType));
247 * In 3.3 we only support the above import proposals, see
248 * CompletionProposal#getRequiredProposals()
250 Assert.isTrue(false);
253 /* Add imports if the preference is on. */
254 importcompletionproposal.fImportRewrite= importcompletionproposal.createImportRewrite();
255 if (importcompletionproposal.fImportRewrite != null) {
256 if (proposalKind == CompletionProposal.TYPE_IMPORT) {
257 String simpleType= importcompletionproposal.fImportRewrite.addImport(qualifiedTypeName, this);
258 if (importcompletionproposal.fParentProposalKind == CompletionProposal.METHOD_REF)
259 return simpleType + "."; //$NON-NLS-1$
261 String res= importcompletionproposal.fImportRewrite.addStaticImport(qualifiedTypeName, String.valueOf(importcompletionproposal.fProposal.getName()), proposalKind == CompletionProposal.FIELD_IMPORT, this);
262 int dot= res.lastIndexOf('.');
264 String typeName= importcompletionproposal.fImportRewrite.addImport(res.substring(0, dot), this);
265 return typeName + '.';
268 return ""; //$NON-NLS-1$
271 // Case where we don't have an import rewrite (see allowAddingImports)
273 if (importcompletionproposal.fCompilationUnit != null && JavaModelUtil.isImplicitImport(Signature.getQualifier(qualifiedTypeName), importcompletionproposal.fCompilationUnit)) {
274 /* No imports for implicit imports. */
276 if (importcompletionproposal.fProposal.getKind() == CompletionProposal.TYPE_IMPORT && importcompletionproposal.fParentProposalKind == CompletionProposal.FIELD_REF)
277 return ""; //$NON-NLS-1$
278 qualifiedTypeName= String.valueOf(Signature.getSignatureSimpleName(qualifiedType));
281 return qualifiedTypeName + ".";