]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/core extension/org/eclipse/jdt/internal/corext/codemanipulation/ContextSensitiveImportRewriteContext.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core extension / org / eclipse / jdt / internal / corext / codemanipulation / ContextSensitiveImportRewriteContext.java
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
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.codemanipulation;
12
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16
17 import org.eclipse.core.runtime.Assert;
18
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;
38
39 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
40 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
41
42 import org.eclipse.jdt.internal.ui.text.java.ImportCompletionProposal;
43
44 /**
45  * This <code>ImportRewriteContext</code> is aware of all the types visible in
46  * <code>compilationUnit</code> at <code>position</code>.
47  * <p>
48  * <b>Note:</b> This context only works if the AST was created with bindings!
49  * </p>
50  */
51 public class ContextSensitiveImportRewriteContext extends ImportRewriteContext {
52
53         private final CompilationUnit fCompilationUnit;
54         private final int fPosition;
55         private IBinding[] fDeclarationsInScope;
56         private Name[] fImportedNames;
57         private final ImportRewrite fImportRewrite;
58
59         /**
60          * Creates an import rewrite context at the given node's start position.
61          * 
62          * @param node the node to use as context
63          * @param importRewrite the import rewrite
64          * 
65          * @since 3.6
66          */
67         public ContextSensitiveImportRewriteContext(ASTNode node, ImportRewrite importRewrite) {
68                 this((CompilationUnit)node.getRoot(), node.getStartPosition(), importRewrite);
69         }
70         
71         /**
72          * Creates an import rewrite context at the given start position.
73          * 
74          * @param compilationUnit the root
75          * @param position the context position
76          * @param importRewrite the import rewrite
77          */
78         public ContextSensitiveImportRewriteContext(CompilationUnit compilationUnit, int position, ImportRewrite importRewrite) {
79                 fCompilationUnit= compilationUnit;
80                 fPosition= position;
81                 fImportRewrite= importRewrite;
82                 fDeclarationsInScope= null;
83                 fImportedNames= null;
84         }
85
86         @Override
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;
96                                 }
97                         } else if (declarationsInScope[i] != null) {
98                                 if (isConflicting(declarationsInScope[i], name)) {
99                                         return RES_NAME_CONFLICT;
100                                 }
101                         }
102                 }
103
104
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;
112                                 }
113                         }
114                 }
115
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;
123                                 } else {
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();
130                                         }
131                                 }
132                         }
133                 }
134
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;
141                         } else {
142                                 if (isConflicting(name, addedImport))
143                                         return RES_NAME_CONFLICT;
144                         }
145                 }
146
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();
152                                 try {
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;
162                                                 }
163                                         }
164                                 } catch (JavaModelException e) {
165                                 }
166                         }
167                 }
168
169                 return fImportRewrite.getDefaultImportRewriteContext().findInContext(qualifier, name, kind);
170         }
171
172         private boolean isConflicting(String name, String importt) {
173                 int index= importt.lastIndexOf('.');
174                 String importedName;
175                 if (index == -1) {
176                         importedName= importt;
177                 } else {
178                         importedName= importt.substring(index + 1, importt.length());
179                 }
180                 if (importedName.equals(name)) {
181                         return true;
182                 }
183                 return false;
184         }
185
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)) {
191                                 return childBinding;
192                         } else {
193                                 ITypeBinding result= containingDeclaration(childBinding, qualifier, name);
194                                 if (result != null) {
195                                         return result;
196                                 }
197                         }
198                 }
199                 return null;
200         }
201
202         private boolean isConflicting(IBinding binding, String name) {
203                 return binding.getName().equals(name);
204         }
205
206         private boolean isSameType(ITypeBinding binding, String qualifier, String name) {
207                 String qualifiedName= JavaModelUtil.concatenateName(qualifier, name);
208                 return binding.getQualifiedName().equals(qualifiedName);
209         }
210
211         private boolean isConflictingType(ITypeBinding binding, String qualifier, String name) {
212                 binding= binding.getTypeDeclaration();
213                 return !isSameType(binding, qualifier, name) && isConflicting(binding, name);
214         }
215
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);
220                 }
221                 return fDeclarationsInScope;
222         }
223
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();
230
231                         List<SimpleName> imports= new ArrayList<SimpleName>();
232                         ImportReferencesCollector.collect(fCompilationUnit, project, null, imports, null);
233                         fImportedNames= imports.toArray(new Name[imports.size()]);
234                 }
235                 return fImportedNames;
236         }
237
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));
245                 } else {
246                         /*
247                          * In 3.3 we only support the above import proposals, see
248                          * CompletionProposal#getRequiredProposals()
249                          */
250                          Assert.isTrue(false);
251                 }
252         
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$
260                         } else {
261                                 String res= importcompletionproposal.fImportRewrite.addStaticImport(qualifiedTypeName, String.valueOf(importcompletionproposal.fProposal.getName()), proposalKind == CompletionProposal.FIELD_IMPORT, this);
262                                 int dot= res.lastIndexOf('.');
263                                 if (dot != -1) {
264                                         String typeName= importcompletionproposal.fImportRewrite.addImport(res.substring(0, dot), this);
265                                         return typeName + '.';
266                                 }
267                         }
268                         return ""; //$NON-NLS-1$
269                 }
270         
271                 // Case where we don't have an import rewrite (see allowAddingImports)
272         
273                 if (importcompletionproposal.fCompilationUnit != null && JavaModelUtil.isImplicitImport(Signature.getQualifier(qualifiedTypeName), importcompletionproposal.fCompilationUnit)) {
274                         /* No imports for implicit imports. */
275         
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));
279                 }
280         
281                 return qualifiedTypeName + ".";
282         }
283 }