bfc9a09535654533a2fcd4fac746039b35df7042
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / DefaultBindingResolver.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
12
13 import java.util.HashMap;
14 import java.util.Map;
15
16 import net.sourceforge.phpdt.core.WorkingCopyOwner;
17 import net.sourceforge.phpdt.core.compiler.CharOperation;
18 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
19 import net.sourceforge.phpdt.internal.compiler.ast.AbstractVariableDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression;
21 import net.sourceforge.phpdt.internal.compiler.ast.ArrayAllocationExpression;
22 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
24 import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
25 import net.sourceforge.phpdt.internal.compiler.ast.JavadocImplicitTypeReference;
26 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
27 import net.sourceforge.phpdt.internal.compiler.ast.JavadocAllocationExpression;
28 import net.sourceforge.phpdt.internal.compiler.ast.JavadocFieldReference;
29 import net.sourceforge.phpdt.internal.compiler.ast.JavadocMessageSend;
30 import net.sourceforge.phpdt.internal.compiler.ast.JavadocQualifiedTypeReference;
31 import net.sourceforge.phpdt.internal.compiler.ast.JavadocSingleNameReference;
32 import net.sourceforge.phpdt.internal.compiler.ast.JavadocSingleTypeReference;
33 import net.sourceforge.phpdt.internal.compiler.ast.Literal;
34 import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
35 import net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair;
36 import net.sourceforge.phpdt.internal.compiler.ast.MessageSend;
37 import net.sourceforge.phpdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
38 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
39 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference;
40 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
41 import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
42 import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
43 import net.sourceforge.phpdt.internal.compiler.ast.ThisReference;
44 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
45 import org.eclipse.jdt.internal.compiler.impl.Constant;
46 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
47 import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
48 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
49 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
50 import net.sourceforge.phpdt.internal.compiler.lookup.ElementValuePair;
51 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
52 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
53 import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
54 import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
55 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding;
56 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
57 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
58 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
59 import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
60 import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
61 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
62 import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
63 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
64 import org.eclipse.jdt.internal.core.util.Util;
65
66 /**
67  * Internal class for resolving bindings using old ASTs.
68  * <p>
69  * IMPORTANT: The methods on this class are synchronized. This is required
70  * because there may be multiple clients in separate threads concurrently
71  * reading an AST and asking for bindings for its nodes. These requests all
72  * end up invoking instance methods on this class. There are various internal
73  * tables and caches which are built and maintained in the course of looking
74  * up bindings. To ensure that they remain coherent in the presence of multiple
75  * threads, the methods are synchronized on the DefaultBindingResolver instance.
76  * </p>
77  */
78 class DefaultBindingResolver extends BindingResolver {
79
80         /*
81          * Holds on binding tables that can be shared by several ASTs.
82          */
83         static class BindingTables {
84
85                 /**
86                  * This map is used to get a binding from its binding key.
87                  */
88                 Map bindingKeysToBindings;
89                 /**
90                  * This map is used to keep the correspondance between new bindings and the
91                  * compiler bindings as well as new annotation instances to their internal counterpart.
92                  * This is an identity map. We should only create one object for one binding or annotation.
93                  */
94                 Map compilerBindingsToASTBindings;
95
96                 BindingTables() {
97                         this.compilerBindingsToASTBindings = new HashMap();
98                         this.bindingKeysToBindings = new HashMap();
99                 }
100
101         }
102         /**
103          * This map is used to retrieve the corresponding block scope for a ast node
104          */
105         Map astNodesToBlockScope;
106
107         /**
108          * This map is used to get an ast node from its binding (new binding) or DOM
109          */
110         Map bindingsToAstNodes;
111
112         /*
113          * The shared binding tables accros ASTs.
114          */
115         BindingTables bindingTables;
116
117         /**
118          * This map is used to retrieve an old ast node using the new ast node. This is not an
119          * identity map.
120          */
121         Map newAstToOldAst;
122
123         /**
124          * Compilation unit scope
125          */
126         private CompilationUnitScope scope;
127
128         /**
129          * The working copy owner that defines the context in which this resolver is creating the bindings.
130          */
131         WorkingCopyOwner workingCopyOwner;
132
133         /**
134          * Toggle controlling whether DOM bindings should be created when missing internal compiler bindings..
135          */
136         boolean isRecoveringBindings;
137
138         /**
139          * Constructor for DefaultBindingResolver.
140          */
141         DefaultBindingResolver(CompilationUnitScope scope, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveringBindings) {
142                 this.newAstToOldAst = new HashMap();
143                 this.astNodesToBlockScope = new HashMap();
144                 this.bindingsToAstNodes = new HashMap();
145                 this.bindingTables = bindingTables;
146                 this.scope = scope;
147                 this.workingCopyOwner = workingCopyOwner;
148                 this.isRecoveringBindings = isRecoveringBindings;
149         }
150
151         DefaultBindingResolver(LookupEnvironment lookupEnvironment, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveringBindings) {
152                 this.newAstToOldAst = new HashMap();
153                 this.astNodesToBlockScope = new HashMap();
154                 this.bindingsToAstNodes = new HashMap();
155                 this.bindingTables = bindingTables;
156                 this.scope = new CompilationUnitScope(new CompilationUnitDeclaration(null, null, -1), lookupEnvironment);
157                 this.workingCopyOwner = workingCopyOwner;
158                 this.isRecoveringBindings = isRecoveringBindings;
159         }
160
161         /*
162          * Method declared on BindingResolver.
163          */
164         synchronized ASTNode findDeclaringNode(IBinding binding) {
165                 if (binding == null) {
166                         return null;
167                 }
168                 if (binding instanceof IMethodBinding) {
169                         IMethodBinding methodBinding = (IMethodBinding) binding;
170                         return (ASTNode) this.bindingsToAstNodes.get(methodBinding.getMethodDeclaration());
171                 } else if (binding instanceof ITypeBinding) {
172                         ITypeBinding typeBinding = (ITypeBinding) binding;
173                         return (ASTNode) this.bindingsToAstNodes.get(typeBinding.getTypeDeclaration());
174                 } else if (binding instanceof IVariableBinding) {
175                         IVariableBinding variableBinding = (IVariableBinding) binding;
176                         return (ASTNode) this.bindingsToAstNodes.get(variableBinding.getVariableDeclaration());
177                 }
178                 return (ASTNode) this.bindingsToAstNodes.get(binding);
179         }
180
181         synchronized ASTNode findDeclaringNode(String bindingKey) {
182                 if (bindingKey == null) {
183                         return null;
184                 }
185                 Object binding = this.bindingTables.bindingKeysToBindings.get(bindingKey);
186                 if (binding == null)
187                         return null;
188                 return (ASTNode) this.bindingsToAstNodes.get(binding);
189         }
190
191         IBinding getBinding(net.sourceforge.phpdt.internal.compiler.lookup.Binding binding) {
192                 switch (binding.kind()) {
193                         case Binding.PACKAGE:
194                                 return getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) binding);
195                         case Binding.TYPE:
196                         case Binding.BASE_TYPE:
197                         case Binding.GENERIC_TYPE:
198                         case Binding.PARAMETERIZED_TYPE:
199                         case Binding.RAW_TYPE:
200                                 return getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
201                         case Binding.ARRAY_TYPE:
202                         case Binding.TYPE_PARAMETER:
203                                 return new TypeBinding(this, (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
204                         case Binding.METHOD:
205                                 return getMethodBinding((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) binding);
206                         case Binding.FIELD:
207                         case Binding.LOCAL:
208                                 return getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding) binding);
209                 }
210                 return null;
211         }
212         
213         Util.BindingsToNodesMap getBindingsToNodesMap() {
214                 return new Util.BindingsToNodesMap() {
215                         public net.sourceforge.phpdt.internal.compiler.ast.ASTNode get(Binding binding) {
216                                 return (net.sourceforge.phpdt.internal.compiler.ast.ASTNode)
217                                         DefaultBindingResolver.this.newAstToOldAst.get(DefaultBindingResolver.this.bindingsToAstNodes.get(binding));
218                         }
219                 };
220         }
221
222         synchronized net.sourceforge.phpdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
223                 return (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
224         }
225
226         /*
227          * Method declared on BindingResolver.
228          */
229         synchronized IMethodBinding getMethodBinding(net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding) {
230                 if (methodBinding != null && !methodBinding.isValidBinding()) {
231                         net.sourceforge.phpdt.internal.compiler.lookup.ProblemMethodBinding problemMethodBinding =
232                                 (net.sourceforge.phpdt.internal.compiler.lookup.ProblemMethodBinding) methodBinding;
233                         methodBinding = problemMethodBinding.closestMatch;
234                 }
235
236                 if (methodBinding != null) {
237                         if (!isRecoveringBindings && ((methodBinding.tagBits & TagBits.HasMissingType) != 0)) {
238                                 return null;
239                         }
240                         IMethodBinding binding = (IMethodBinding) this.bindingTables.compilerBindingsToASTBindings.get(methodBinding);
241                         if (binding != null) {
242                                 return binding;
243                         }
244                         binding = new MethodBinding(this, methodBinding);
245                         this.bindingTables.compilerBindingsToASTBindings.put(methodBinding, binding);
246                         return binding;
247                 }
248                 return null;
249         }
250
251         synchronized IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair valuePair) {
252                 if (valuePair == null || valuePair.binding == null) return null;
253                 IMemberValuePairBinding binding =
254                         (IMemberValuePairBinding) this.bindingTables.compilerBindingsToASTBindings.get(valuePair);
255                 if (binding != null)
256                         return binding;
257                 binding = new MemberValuePairBinding(valuePair, this);
258                 this.bindingTables.compilerBindingsToASTBindings.put(valuePair, binding);
259                 return binding;
260         }
261
262         /*
263          * Method declared on BindingResolver.
264          */
265         synchronized IPackageBinding getPackageBinding(net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding packageBinding) {
266                 if (packageBinding == null) {
267                         return null;
268                 }
269                 IPackageBinding binding = (IPackageBinding) this.bindingTables.compilerBindingsToASTBindings.get(packageBinding);
270                 if (binding != null) {
271                         return binding;
272                 }
273                 binding = new PackageBinding(packageBinding, this);
274                 this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
275                 return binding;
276         }
277         private int getTypeArguments(ParameterizedQualifiedTypeReference typeReference) {
278                 TypeReference[][] typeArguments = typeReference.typeArguments;
279                 int value = 0;
280                 for (int i = 0, max = typeArguments.length; i < max; i++) {
281                         if ((typeArguments[i] != null) || (value != 0)) {
282                                 value++;
283                         }
284                 }
285                 return value;
286         }
287
288         /**
289          * Returns the new type binding corresponding to the given variable declaration.
290          * This is used for recovered binding only.
291          * <p>
292          * The default implementation of this method returns <code>null</code>.
293          * Subclasses may reimplement.
294          * </p>
295          *
296          * @param variableDeclaration the given variable declaration
297          * @return the new type binding
298          */
299         synchronized ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
300                 ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableDeclaration);
301                 if (binding != null) {
302                         return binding;
303                 }
304                 binding = new RecoveredTypeBinding(this, variableDeclaration);
305                 this.bindingTables.compilerBindingsToASTBindings.put(variableDeclaration, binding);
306                 return binding;
307         }
308
309         /**
310          * Returns the new type binding corresponding to the given type.
311          * This is used for recovered binding only.
312          * <p>
313          * The default implementation of this method returns <code>null</code>.
314          * Subclasses may reimplement.
315          * </p>
316          *
317          * @param type the given type
318          * @return the new type binding
319          */
320         synchronized ITypeBinding getTypeBinding(Type type) {
321                 ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(type);
322                 if (binding != null) {
323                         return binding;
324                 }
325                 binding = new RecoveredTypeBinding(this, type);
326                 this.bindingTables.compilerBindingsToASTBindings.put(type, binding);
327                 return binding;
328         }
329
330         /*
331          * Method declared on BindingResolver.
332          */
333         synchronized ITypeBinding getTypeBinding(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding referenceBinding) {
334                 if (referenceBinding == null) {
335                         return null;
336                 } else if (!referenceBinding.isValidBinding()) {
337                         switch(referenceBinding.problemId()) {
338                                 case ProblemReasons.NotVisible :
339                                 case ProblemReasons.NonStaticReferenceInStaticContext :
340                                         if (referenceBinding instanceof ProblemReferenceBinding) {
341                                                 ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) referenceBinding;
342                                                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding2 = problemReferenceBinding.closestMatch();
343                                                 ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(binding2);
344                                                 if (binding != null) {
345                                                         return binding;
346                                                 }
347                                                 binding = new TypeBinding(this, binding2);
348                                                 this.bindingTables.compilerBindingsToASTBindings.put(binding2, binding);
349                                                 return binding;
350                                         }
351                                         break;
352                                 case ProblemReasons.NotFound :
353                                         if (!this.isRecoveringBindings) {
354                                                 return null;
355                                         }
356                                         ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
357                                         if (binding != null) {
358                                                 return binding;
359                                         }
360                                         if ((referenceBinding.tagBits & TagBits.HasMissingType) != 0) {
361                                                 binding = new TypeBinding(this, referenceBinding);
362                                         } else {
363                                                 binding = new RecoveredTypeBinding(this, referenceBinding);
364                                         }
365                                         this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
366                                         return binding;
367                         }
368                         return null;
369                 } else {
370                         if ((referenceBinding.tagBits & TagBits.HasMissingType) != 0 && !this.isRecoveringBindings) {
371                                 return null;
372                         }
373                         ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
374                         if (binding != null) {
375                                 return binding;
376                         }
377                         binding = new TypeBinding(this, referenceBinding);
378                         this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
379                         return binding;
380                 }
381         }
382
383         /*
384          * Method declared on BindingResolver.
385          */
386         synchronized ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
387                 if (recoveredTypeBinding== null) {
388                         return null;
389                 }
390                 return new RecoveredTypeBinding(this, recoveredTypeBinding, dimensions);
391         }
392
393         synchronized IVariableBinding getVariableBinding(net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding variableBinding, VariableDeclaration variableDeclaration) {
394                 if (this.isRecoveringBindings) {
395                         if (variableBinding != null) {
396                                 if (variableBinding.isValidBinding()) {
397                                         IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
398                                         if (binding != null) {
399                                                 return binding;
400                                         }
401                                         if (variableBinding.type != null) {
402                                                 binding = new VariableBinding(this, variableBinding);
403                                         } else {
404                                                 binding = new RecoveredVariableBinding(this, variableDeclaration);
405                                         }
406                                         this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
407                                         return binding;
408                                 } else {
409                                         /*
410                                          * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
411                                          */
412                                         if (variableBinding instanceof ProblemFieldBinding) {
413                                                 ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
414                                                 switch(problemFieldBinding.problemId()) {
415                                                         case ProblemReasons.NotVisible :
416                                                         case ProblemReasons.NonStaticReferenceInStaticContext :
417                                                         case ProblemReasons.NonStaticReferenceInConstructorInvocation :
418                                                                 ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
419                                                                 FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
420                                                                 if (exactBinding != null) {
421                                                                         IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
422                                                                         if (variableBinding2 != null) {
423                                                                                 return variableBinding2;
424                                                                         }
425                                                                         variableBinding2 = new VariableBinding(this, exactBinding);
426                                                                         this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
427                                                                         return variableBinding2;
428                                                                 }
429                                                                 break;
430                                                 }
431                                         }
432                                 }
433                         }
434                         return null;
435                 }
436                 return this.getVariableBinding(variableBinding);
437         }
438
439         public WorkingCopyOwner getWorkingCopyOwner() {
440                 return this.workingCopyOwner;
441         }
442
443         /*
444          * Method declared on BindingResolver.
445          */
446         synchronized IVariableBinding getVariableBinding(net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding variableBinding) {
447                 if (variableBinding != null) {
448                         if (variableBinding.isValidBinding()) {
449                                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding variableType = variableBinding.type;
450                                 if (variableType != null) {
451                                         if (!this.isRecoveringBindings && ((variableType.tagBits & TagBits.HasMissingType) != 0)) {
452                                                 return null;
453                                         }
454                                         IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
455                                         if (binding != null) {
456                                                 return binding;
457                                         }
458                                         binding = new VariableBinding(this, variableBinding);
459                                         this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
460                                         return binding;
461                                 }
462                         } else {
463                                 /*
464                                  * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
465                                  */
466                                 if (variableBinding instanceof ProblemFieldBinding) {
467                                         ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
468                                         switch(problemFieldBinding.problemId()) {
469                                                 case ProblemReasons.NotVisible :
470                                                 case ProblemReasons.NonStaticReferenceInStaticContext :
471                                                 case ProblemReasons.NonStaticReferenceInConstructorInvocation :
472                                                         ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
473                                                         FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
474                                                         if (exactBinding != null) {
475                                                                 IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
476                                                                 if (variableBinding2 != null) {
477                                                                         return variableBinding2;
478                                                                 }
479                                                                 variableBinding2 = new VariableBinding(this, exactBinding);
480                                                                 this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
481                                                                 return variableBinding2;
482                                                         }
483                                                         break;
484                                         }
485                                 }
486                         }
487                 }
488                 return null;
489         }
490
491         synchronized IAnnotationBinding getAnnotationInstance(net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalInstance) {
492                 if (internalInstance == null) return null;
493                 ReferenceBinding annotationType = internalInstance.getAnnotationType();
494                 if (!this.isRecoveringBindings) {
495                         if (annotationType == null || ((annotationType.tagBits & TagBits.HasMissingType) != 0)) {
496                                 return null;
497                         }
498                 }
499                 IAnnotationBinding domInstance =
500                         (IAnnotationBinding) this.bindingTables.compilerBindingsToASTBindings.get(internalInstance);
501                 if (domInstance != null)
502                         return domInstance;
503                 domInstance = new AnnotationBinding(internalInstance, this);
504                 this.bindingTables.compilerBindingsToASTBindings.put(internalInstance, domInstance);
505                 return domInstance;
506         }
507
508         boolean isResolvedTypeInferredFromExpectedType(MethodInvocation methodInvocation) {
509                 Object oldNode = this.newAstToOldAst.get(methodInvocation);
510                 if (oldNode instanceof MessageSend) {
511                         MessageSend messageSend = (MessageSend) oldNode;
512                         net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
513                         if (methodBinding instanceof ParameterizedGenericMethodBinding) {
514                                 ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
515                                 return genericMethodBinding.inferredReturnType;
516                         }
517                 }
518                 return false;
519         }
520
521         boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation superMethodInvocation) {
522                 Object oldNode = this.newAstToOldAst.get(superMethodInvocation);
523                 if (oldNode instanceof MessageSend) {
524                         MessageSend messageSend = (MessageSend) oldNode;
525                         net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
526                         if (methodBinding instanceof ParameterizedGenericMethodBinding) {
527                                 ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
528                                 return genericMethodBinding.inferredReturnType;
529                         }
530                 }
531                 return false;
532         }
533
534         /*
535          * Method declared on BindingResolver.
536          */
537         LookupEnvironment lookupEnvironment() {
538                 return this.scope.environment();
539         }
540
541         /**
542          * @see org.eclipse.jdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
543          */
544         synchronized void recordScope(ASTNode astNode, BlockScope blockScope) {
545                 this.astNodesToBlockScope.put(astNode, blockScope);
546         }
547
548         /*
549          * @see BindingResolver#resolveBoxing(Expression)
550          */
551         boolean resolveBoxing(Expression expression) {
552                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
553                 if (node != null && (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression)) {
554                         net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) node;
555                         return (compilerExpression.implicitConversion & TypeIds.BOXING) != 0;
556                 }
557                 return false;
558         }
559
560         /*
561          * @see BindingResolver#resolveUnboxing(Expression)
562          */
563         boolean resolveUnboxing(Expression expression) {
564                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
565                 if (node != null && (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression)) {
566                         net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) node;
567                         return (compilerExpression.implicitConversion & TypeIds.UNBOXING) != 0;
568                 }
569                 return false;
570         }
571
572         /*
573          * @see BindingResolver#resolveConstantExpressionValue(Expression)
574          */
575         Object resolveConstantExpressionValue(Expression expression) {
576                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
577                 if (node != null && (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression)) {
578                         net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) node;
579                         Constant constant = compilerExpression.constant;
580                         if (constant != null && constant != Constant.NotAConstant) {
581                                 switch (constant.typeID()) {
582                                         case TypeIds.T_int : return new Integer(constant.intValue());
583                                         case TypeIds.T_byte : return new Byte(constant.byteValue());
584                                         case TypeIds.T_short : return new Short(constant.shortValue());
585                                         case TypeIds.T_char : return new Character(constant.charValue());
586                                         case TypeIds.T_float : return new Float(constant.floatValue());
587                                         case TypeIds.T_double : return new Double(constant.doubleValue());
588                                         case TypeIds.T_boolean : return constant.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
589                                         case TypeIds.T_long : return new Long(constant.longValue());
590                                         case TypeIds.T_JavaLangString : return constant.stringValue();
591                                 }
592                                 return null;
593                         }
594                 }
595                 return null;
596         }
597
598         /*
599          * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
600          */
601         synchronized IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
602                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
603                 if (node != null && (node.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
604                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
605                         return this.getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
606                 } else if (node instanceof AllocationExpression) {
607                         return this.getMethodBinding(((AllocationExpression)node).binding);
608                 }
609                 return null;
610         }
611
612         /*
613          * @see BindingResolver#resolveConstructor(ConstructorInvocation)
614          */
615         synchronized IMethodBinding resolveConstructor(ConstructorInvocation expression) {
616                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
617                 if (node instanceof ExplicitConstructorCall) {
618                         ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
619                         return this.getMethodBinding(explicitConstructorCall.binding);
620                 }
621                 return null;
622         }
623
624         /* (non-Javadoc)
625          * @see org.eclipse.jdt.core.dom.BindingResolver#resolveConstructor(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
626          */
627         IMethodBinding resolveConstructor(EnumConstantDeclaration enumConstantDeclaration) {
628                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(enumConstantDeclaration);
629                 if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
630                         net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
631                         if (fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT && fieldDeclaration.initialization != null) {
632                                 AllocationExpression allocationExpression = (AllocationExpression) fieldDeclaration.initialization;
633                                 return this.getMethodBinding(allocationExpression.binding);
634                         }
635                 }
636                 return null;
637         }
638
639         /*
640          * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
641          */
642         synchronized IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
643                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
644                 if (node instanceof ExplicitConstructorCall) {
645                         ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
646                         return this.getMethodBinding(explicitConstructorCall.binding);
647                 }
648                 return null;
649         }
650         /*
651          * Method declared on BindingResolver.
652          */
653         synchronized ITypeBinding resolveExpressionType(Expression expression) {
654                 try {
655                         switch(expression.getNodeType()) {
656                                 case ASTNode.CLASS_INSTANCE_CREATION :
657                                         net.sourceforge.phpdt.internal.compiler.ast.ASTNode astNode = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
658                                         if (astNode instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
659                                                 // anonymous type case
660                                                 net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) astNode;
661                                                 ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
662                                                 if (typeBinding != null) {
663                                                         return typeBinding;
664                                                 }
665                                         } else {
666                                                 // should be an AllocationExpression
667                                                 AllocationExpression allocationExpression = (AllocationExpression) astNode;
668                                                 return this.getTypeBinding(allocationExpression.resolvedType);
669                                         }
670                                         break;
671                                 case ASTNode.SIMPLE_NAME :
672                                 case ASTNode.QUALIFIED_NAME :
673                                         return this.resolveTypeBindingForName((Name) expression);
674                                 case ASTNode.ARRAY_INITIALIZER :
675                                 case ASTNode.ARRAY_CREATION :
676                                 case ASTNode.ASSIGNMENT :
677                                 case ASTNode.POSTFIX_EXPRESSION :
678                                 case ASTNode.PREFIX_EXPRESSION :
679                                 case ASTNode.CAST_EXPRESSION :
680                                 case ASTNode.TYPE_LITERAL :
681                                 case ASTNode.INFIX_EXPRESSION :
682                                 case ASTNode.INSTANCEOF_EXPRESSION :
683                                 case ASTNode.FIELD_ACCESS :
684                                 case ASTNode.SUPER_FIELD_ACCESS :
685                                 case ASTNode.ARRAY_ACCESS :
686                                 case ASTNode.METHOD_INVOCATION :
687                                 case ASTNode.SUPER_METHOD_INVOCATION :
688                                 case ASTNode.CONDITIONAL_EXPRESSION :
689                                 case ASTNode.MARKER_ANNOTATION :
690                                 case ASTNode.NORMAL_ANNOTATION :
691                                 case ASTNode.SINGLE_MEMBER_ANNOTATION :
692                                         net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(expression);
693                                         if (compilerExpression != null) {
694                                                 return this.getTypeBinding(compilerExpression.resolvedType);
695                                         }
696                                         break;
697                                 case ASTNode.STRING_LITERAL :
698                                         if (this.scope != null) {
699                                                 return this.getTypeBinding(this.scope.getJavaLangString());
700                                         }
701                                         break;
702                                 case ASTNode.BOOLEAN_LITERAL :
703                                 case ASTNode.NULL_LITERAL :
704                                 case ASTNode.CHARACTER_LITERAL :
705                                 case ASTNode.NUMBER_LITERAL :
706                                         Literal literal = (Literal) this.newAstToOldAst.get(expression);
707                                         return this.getTypeBinding(literal.literalType(null));
708                                 case ASTNode.THIS_EXPRESSION :
709                                         ThisReference thisReference = (ThisReference) this.newAstToOldAst.get(expression);
710                                         BlockScope blockScope = (BlockScope) this.astNodesToBlockScope.get(expression);
711                                         if (blockScope != null) {
712                                                 return this.getTypeBinding(thisReference.resolveType(blockScope));
713                                         }
714                                         break;
715                                 case ASTNode.PARENTHESIZED_EXPRESSION :
716                                         ParenthesizedExpression parenthesizedExpression = (ParenthesizedExpression) expression;
717                                         return this.resolveExpressionType(parenthesizedExpression.getExpression());
718                                 case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
719                                         VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expression;
720                                         Type type = variableDeclarationExpression.getType();
721                                         if (type != null) {
722                                                 return type.resolveBinding();
723                                         }
724                                         break;
725                         }
726                 } catch (AbortCompilation e) {
727                         // handle missing types
728                 }
729                 return null;
730         }
731
732         /*
733          * @see BindingResolver#resolveField(FieldAccess)
734          */
735         synchronized IVariableBinding resolveField(FieldAccess fieldAccess) {
736                 Object oldNode = this.newAstToOldAst.get(fieldAccess);
737                 if (oldNode instanceof FieldReference) {
738                         FieldReference fieldReference = (FieldReference) oldNode;
739                         return this.getVariableBinding(fieldReference.binding);
740                 }
741                 return null;
742         }
743
744         /*
745          * @see BindingResolver#resolveField(SuperFieldAccess)
746          */
747         synchronized IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
748                 Object oldNode = this.newAstToOldAst.get(fieldAccess);
749                 if (oldNode instanceof FieldReference) {
750                         FieldReference fieldReference = (FieldReference) oldNode;
751                         return this.getVariableBinding(fieldReference.binding);
752                 }
753                 return null;
754         }
755
756         /*
757          * @see BindingResolver#resolveImport(ImportDeclaration)
758          */
759         synchronized IBinding resolveImport(ImportDeclaration importDeclaration) {
760                 if (this.scope == null) return null;
761                 try {
762                         net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(importDeclaration);
763                         if (node instanceof ImportReference) {
764                                 ImportReference importReference = (ImportReference) node;
765                                 final boolean isStatic = importReference.isStatic();
766                                 if ((importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0) {
767                                         Binding binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length), true, isStatic);
768                                         if (binding != null) {
769                                                 if (isStatic) {
770                                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
771                                                                 ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
772                                                                 return typeBinding == null ? null : typeBinding;
773                                                         }
774                                                 } else {
775                                                         if ((binding.kind() & Binding.PACKAGE) != 0) {
776                                                                 IPackageBinding packageBinding = this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) binding);
777                                                                 if (packageBinding == null) {
778                                                                         return null;
779                                                                 }
780                                                                 return packageBinding;
781                                                         } else {
782                                                                 // if it is not a package, it has to be a type
783                                                                 ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
784                                                                 if (typeBinding == null) {
785                                                                         return null;
786                                                                 }
787                                                                 return typeBinding;
788                                                         }
789                                                 }
790                                         }
791                                 } else {
792                                         Binding binding = this.scope.getImport(importReference.tokens, false, isStatic);
793                                         if (binding != null) {
794                                                 if (isStatic) {
795                                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
796                                                                 ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
797                                                                 return typeBinding == null ? null : typeBinding;
798                                                         } else if (binding instanceof FieldBinding) {
799                                                                 IVariableBinding variableBinding = this.getVariableBinding((FieldBinding) binding);
800                                                                 return variableBinding == null ? null : variableBinding;
801                                                         } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) {
802                                                                 // it is a type
803                                                                 return this.getMethodBinding((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding)binding);
804                                                         }
805                                                 } else {
806                                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
807                                                                 ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
808                                                                 return typeBinding == null ? null : typeBinding;
809                                                         }
810                                                 }
811                                         }
812                                 }
813                         }
814                 } catch(AbortCompilation e) {
815                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
816                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
817                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
818                 }
819                 return null;
820         }
821
822         /* (non-Javadoc)
823          * @see org.eclipse.jdt.core.dom.BindingResolver#resolveMember(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
824          */
825         IMethodBinding resolveMember(AnnotationTypeMemberDeclaration declaration) {
826                 Object oldNode = this.newAstToOldAst.get(declaration);
827                 if (oldNode instanceof AbstractMethodDeclaration) {
828                         AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
829                         IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
830                         if (methodBinding == null) {
831                                 return null;
832                         }
833                         this.bindingsToAstNodes.put(methodBinding, declaration);
834                         String key = methodBinding.getKey();
835                         if (key != null) {
836                                 this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
837                         }
838                         return methodBinding;
839                 }
840                 return null;
841         }
842
843         /*
844          * Method declared on BindingResolver.
845          */
846         synchronized IMethodBinding resolveMethod(MethodDeclaration method) {
847                 Object oldNode = this.newAstToOldAst.get(method);
848                 if (oldNode instanceof AbstractMethodDeclaration) {
849                         AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
850                         IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
851                         if (methodBinding == null) {
852                                 return null;
853                         }
854                         this.bindingsToAstNodes.put(methodBinding, method);
855                         String key = methodBinding.getKey();
856                         if (key != null) {
857                                 this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
858                         }
859                         return methodBinding;
860                 }
861                 return null;
862         }
863         /*
864          * Method declared on BindingResolver.
865          */
866         synchronized IMethodBinding resolveMethod(MethodInvocation method) {
867                 Object oldNode = this.newAstToOldAst.get(method);
868                 if (oldNode instanceof MessageSend) {
869                         MessageSend messageSend = (MessageSend) oldNode;
870                         return this.getMethodBinding(messageSend.binding);
871                 }
872                 return null;
873         }
874         /*
875          * Method declared on BindingResolver.
876          */
877         synchronized IMethodBinding resolveMethod(SuperMethodInvocation method) {
878                 Object oldNode = this.newAstToOldAst.get(method);
879                 if (oldNode instanceof MessageSend) {
880                         MessageSend messageSend = (MessageSend) oldNode;
881                         return this.getMethodBinding(messageSend.binding);
882                 }
883                 return null;
884         }
885
886         synchronized ITypeBinding resolveTypeBindingForName(Name name) {
887                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
888                 int index = name.index;
889                 if (node instanceof QualifiedNameReference) {
890                         QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
891                         final char[][] tokens = qualifiedNameReference.tokens;
892                         if (tokens.length == index) {
893                                 return this.getTypeBinding(qualifiedNameReference.resolvedType);
894                         }
895                         int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
896                         if (index < indexOfFirstFieldBinding) {
897                                 // an extra lookup is required
898                                 BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
899                                 Binding binding = null;
900                                 try {
901                                         if (internalScope == null) {
902                                                 if (this.scope == null) return null;
903                                                 binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
904                                         } else {
905                                                 binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
906                                         }
907                                 } catch (AbortCompilation e) {
908                                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
909                                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
910                                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
911                                 }
912                                 if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
913                                         return null;
914                                 } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
915                                         // it is a type
916                                         return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
917                                 }
918                         } else if (index == indexOfFirstFieldBinding) {
919                                 if (qualifiedNameReference.isTypeReference()) {
920                                         return this.getTypeBinding(qualifiedNameReference.resolvedType);
921                                 } else {
922                                         // in this case we want to get the next field declaring's class
923                                         if (qualifiedNameReference.otherBindings == null) {
924                                                 return null;
925                                         }
926                                         FieldBinding fieldBinding = qualifiedNameReference.otherBindings[0];
927                                         if (fieldBinding == null) return null;
928                                         net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
929                                         if (type == null) { // array length scenario
930                                                 // use type from first binding (no capture needed for array type)
931                                                 switch (qualifiedNameReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.RestrictiveFlagMASK) {
932                                                         case Binding.FIELD:
933                                                                 type = ((FieldBinding) qualifiedNameReference.binding).type;
934                                                                 break;
935                                                         case Binding.LOCAL:
936                                                                 type = ((LocalVariableBinding) qualifiedNameReference.binding).type;
937                                                                 break;
938                                                 }
939                                         }
940                                         return this.getTypeBinding(type);
941                                 }
942                         } else {
943                                 /* This is the case for a name which is part of a qualified name that
944                                  * cannot be resolved. See PR 13063.
945                                  */
946                                 if (qualifiedNameReference.otherBindings == null) return null;
947                                 final int otherBindingsLength = qualifiedNameReference.otherBindings.length;
948                                 if (otherBindingsLength == (index - indexOfFirstFieldBinding)) {
949                                         return this.getTypeBinding(qualifiedNameReference.resolvedType);
950                                 }
951                                 FieldBinding fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding];
952                                 if (fieldBinding == null) return null;
953                                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
954                                 if (type == null) { // array length scenario
955                                         // use type from previous binding (no capture needed for array type)
956                                         fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1];
957                                         if (fieldBinding == null) return null;
958                                         type = fieldBinding.type;
959                                 }
960                                 return this.getTypeBinding(type);
961                         }
962                 } else if (node instanceof QualifiedTypeReference) {
963                         QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
964                         if (qualifiedTypeReference.resolvedType == null) {
965                                 return null;
966                         }
967                         if (index == qualifiedTypeReference.tokens.length) {
968                                 if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
969                                         JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
970                                         if (typeRef.packageBinding != null) {
971                                                 return null;
972                                         }
973                                 }
974                                 return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
975                         } else {
976                                 if (index >= 0) {
977                                         BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
978                                         Binding binding = null;
979                                         try {
980                                                 if (internalScope == null) {
981                                                         if (this.scope == null) return null;
982                                                         binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
983                                                 } else {
984                                                         binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
985                                                 }
986                                         } catch (AbortCompilation e) {
987                                                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
988                                         }
989                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
990                                                 return null;
991                                         } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
992                                                 // it is a type
993                                                 return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
994                                         } else {
995                                                 return null;
996                                         }
997                                 }
998                         }
999                 } else if (node instanceof ImportReference) {
1000                         ImportReference importReference = (ImportReference) node;
1001                         int importReferenceLength = importReference.tokens.length;
1002                         if (index >= 0) {
1003                                 Binding binding = null;
1004                                 if (this.scope == null) return null;
1005                                 if (importReferenceLength == index) {
1006                                         try {
1007                                                 binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
1008                                         } catch (AbortCompilation e) {
1009                                                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1010                                         }
1011                                 } else {
1012                                         try {
1013                                                 binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
1014                                         } catch (AbortCompilation e) {
1015                                                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1016                                         }
1017                                 }
1018                                 if (binding != null) {
1019                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
1020                                                 // it is a type
1021                                                 return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
1022                                         }
1023                                         return null;
1024                                 }
1025                         }
1026                 } else if (node instanceof AbstractMethodDeclaration) {
1027                         AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
1028                         IMethodBinding method = this.getMethodBinding(methodDeclaration.binding);
1029                         if (method == null) return null;
1030                         return method.getReturnType();
1031                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
1032                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
1033                         ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
1034                         if (typeBinding != null) {
1035                                 return typeBinding;
1036                         }
1037                 } if (node instanceof JavadocSingleNameReference) {
1038                         JavadocSingleNameReference singleNameReference = (JavadocSingleNameReference) node;
1039                         LocalVariableBinding localVariable = (LocalVariableBinding)singleNameReference.binding;
1040                         if (localVariable != null) {
1041                                 return this.getTypeBinding(localVariable.type);
1042                         }
1043                 } if (node instanceof SingleNameReference) {
1044                         SingleNameReference singleNameReference = (SingleNameReference) node;
1045                         return this.getTypeBinding(singleNameReference.resolvedType);
1046                 } else if (node instanceof QualifiedSuperReference) {
1047                         QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
1048                         return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
1049                 } else if (node instanceof LocalDeclaration) {
1050                         IVariableBinding variable = this.getVariableBinding(((LocalDeclaration)node).binding);
1051                         if (variable == null) return null;
1052                         return variable.getType();
1053                 } else if (node instanceof JavadocFieldReference) {
1054                         JavadocFieldReference fieldRef = (JavadocFieldReference) node;
1055                         if (fieldRef.methodBinding != null) {
1056                                 return getMethodBinding(fieldRef.methodBinding).getReturnType();
1057                         }
1058                         return getTypeBinding(fieldRef.resolvedType);
1059                 } else if (node instanceof FieldReference) {
1060                         return getTypeBinding(((FieldReference) node).resolvedType);
1061                 } else if (node instanceof SingleTypeReference) {
1062                         SingleTypeReference singleTypeReference = (SingleTypeReference) node;
1063                         net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
1064                         if (binding != null) {
1065                                 return this.getTypeBinding(binding.leafComponentType());
1066                         }
1067                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
1068                         net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
1069                         IVariableBinding field = this.getVariableBinding(fieldDeclaration.binding);
1070                         if (field == null) return null;
1071                         return field.getType();
1072                 } else if (node instanceof MessageSend) {
1073                         MessageSend messageSend = (MessageSend) node;
1074                         IMethodBinding method = getMethodBinding(messageSend.binding);
1075                         if (method == null) return null;
1076                         return method.getReturnType();
1077                 } else if (node instanceof AllocationExpression) {
1078                         AllocationExpression allocation = (AllocationExpression) node;
1079                         return getTypeBinding(allocation.resolvedType);
1080                 } else if (node instanceof JavadocImplicitTypeReference) {
1081                         JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
1082                         return getTypeBinding(implicitRef.resolvedType);
1083                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) {
1084                         net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter = (net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) node;
1085                         return this.getTypeBinding(typeParameter.binding);
1086                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) {
1087                         net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair memberValuePair = (net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) node;
1088                         IMethodBinding method = getMethodBinding(memberValuePair.binding);
1089                         if (method == null) return null;
1090                         return method.getReturnType();
1091                 }
1092                 return null;
1093         }
1094
1095         /*
1096          * Method declared on BindingResolver.
1097          */
1098         synchronized IBinding resolveName(Name name) {
1099                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
1100                 int index = name.index;
1101                 if (node instanceof QualifiedNameReference) {
1102                         QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
1103                         final char[][] tokens = qualifiedNameReference.tokens;
1104                         int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
1105                         if (index < indexOfFirstFieldBinding) {
1106                                 // an extra lookup is required
1107                                 BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
1108                                 Binding binding = null;
1109                                 try {
1110                                         if (internalScope == null) {
1111                                                 if (this.scope == null) return null;
1112                                                 binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
1113                                         } else {
1114                                                 binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
1115                                         }
1116                                 } catch (AbortCompilation e) {
1117                                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1118                                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
1119                                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
1120                                 }
1121                                 if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
1122                                         return this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)binding);
1123                                 } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
1124                                         // it is a type
1125                                         return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
1126                                 }
1127                         } else if (index == indexOfFirstFieldBinding) {
1128                                 if (qualifiedNameReference.isTypeReference()) {
1129                                         return this.getTypeBinding(qualifiedNameReference.resolvedType);
1130                                 } else {
1131                                         Binding binding = qualifiedNameReference.binding;
1132                                         if (binding != null) {
1133                                                 if (binding.isValidBinding()) {
1134                                                         return this.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding) binding);
1135                                                 } else  if (binding instanceof ProblemFieldBinding) {
1136                                                         ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
1137                                                         switch(problemFieldBinding.problemId()) {
1138                                                                 case ProblemReasons.NotVisible :
1139                                                                 case ProblemReasons.NonStaticReferenceInStaticContext :
1140                                                                         ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
1141                                                                         if (declaringClass != null) {
1142                                                                                 FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
1143                                                                                 if (exactBinding != null) {
1144                                                                                         if (exactBinding.type != null) {
1145                                                                                                 IVariableBinding variableBinding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
1146                                                                                                 if (variableBinding != null) {
1147                                                                                                         return variableBinding;
1148                                                                                                 }
1149                                                                                                 variableBinding = new VariableBinding(this, exactBinding);
1150                                                                                                 this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding);
1151                                                                                                 return variableBinding;
1152                                                                                         }
1153                                                                                 }
1154                                                                         }
1155                                                                         break;
1156                                                         }
1157                                                 }
1158                                         }
1159                                 }
1160                         } else {
1161                                 /* This is the case for a name which is part of a qualified name that
1162                                  * cannot be resolved. See PR 13063.
1163                                  */
1164                                 if (qualifiedNameReference.otherBindings == null || (index - indexOfFirstFieldBinding - 1) < 0) {
1165                                         return null;
1166                                 } else {
1167                                         return this.getVariableBinding(qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1]);
1168                                 }
1169                         }
1170                 } else if (node instanceof QualifiedTypeReference) {
1171                         QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
1172                         if (qualifiedTypeReference.resolvedType == null) {
1173                                 return null;
1174                         }
1175                         if (index == qualifiedTypeReference.tokens.length) {
1176                                 if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
1177                                         JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
1178                                         if (typeRef.packageBinding != null) {
1179                                                 return getPackageBinding(typeRef.packageBinding);
1180                                         }
1181                                 }
1182                                 return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
1183                         } else {
1184                                 if (index >= 0) {
1185                                         BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
1186                                         Binding binding = null;
1187                                         try {
1188                                                 if (internalScope == null) {
1189                                                         if (this.scope == null) return null;
1190                                                         binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
1191                                                 } else {
1192                                                         binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
1193                                                 }
1194                                         } catch (AbortCompilation e) {
1195                                                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1196                                         }
1197                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
1198                                                 return this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)binding);
1199                                         } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
1200                                                 // it is a type
1201                                                 return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
1202                                         } else {
1203                                                 return null;
1204                                         }
1205                                 }
1206                         }
1207                 } else if (node instanceof ImportReference) {
1208                         ImportReference importReference = (ImportReference) node;
1209                         int importReferenceLength = importReference.tokens.length;
1210                         if (index >= 0) {
1211                                 Binding binding = null;
1212                                 if (this.scope == null) return null;
1213                                 if (importReferenceLength == index) {
1214                                         try {
1215                                                 binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
1216                                         } catch (AbortCompilation e) {
1217                                                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1218                                         }
1219                                 } else {
1220                                         try {
1221                                                 binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
1222                                         } catch (AbortCompilation e) {
1223                                                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1224                                         }
1225                                 }
1226                                 if (binding != null) {
1227                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
1228                                                 return this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)binding);
1229                                         } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
1230                                                 // it is a type
1231                                                 return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
1232                                         } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding) {
1233                                                 // it is a type
1234                                                 return this.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding)binding);
1235                                         } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) {
1236                                                 // it is a type
1237                                                 return this.getMethodBinding((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding)binding);
1238                                         } else {
1239                                                 return null;
1240                                         }
1241                                 }
1242                         }
1243                 } else if (node instanceof CompilationUnitDeclaration) {
1244                         CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) node;
1245                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
1246                         if (types == null || types.length == 0) {
1247                                 return null;
1248                         }
1249                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration type = types[0];
1250                         if (type != null) {
1251                                 ITypeBinding typeBinding = this.getTypeBinding(type.binding);
1252                                 if (typeBinding != null) {
1253                                         return typeBinding.getPackage();
1254                                 }
1255                         }
1256                 } else if (node instanceof AbstractMethodDeclaration) {
1257                         AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
1258                         IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
1259                         if (methodBinding != null) {
1260                                 return methodBinding;
1261                         }
1262                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
1263                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
1264                         ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
1265                         if (typeBinding != null) {
1266                                 return typeBinding;
1267                         }
1268                 } if (node instanceof SingleNameReference) {
1269                         SingleNameReference singleNameReference = (SingleNameReference) node;
1270                         if (singleNameReference.isTypeReference()) {
1271                                 return this.getTypeBinding(singleNameReference.resolvedType);
1272                         } else {
1273                                 // this is a variable or a field
1274                                 Binding binding = singleNameReference.binding;
1275                                 if (binding != null) {
1276                                         if (binding.isValidBinding()) {
1277                                                 return this.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding) binding);
1278                                         } else {
1279                                                 /*
1280                                                  * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
1281                                                  */
1282                                                 if (binding instanceof ProblemFieldBinding) {
1283                                                         ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
1284                                                         switch(problemFieldBinding.problemId()) {
1285                                                                 case ProblemReasons.NotVisible :
1286                                                                 case ProblemReasons.NonStaticReferenceInStaticContext :
1287                                                                 case ProblemReasons.NonStaticReferenceInConstructorInvocation :
1288                                                                         ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
1289                                                                         FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
1290                                                                         if (exactBinding != null) {
1291                                                                                 if (exactBinding.type != null) {
1292                                                                                         IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
1293                                                                                         if (variableBinding2 != null) {
1294                                                                                                 return variableBinding2;
1295                                                                                         }
1296                                                                                         variableBinding2 = new VariableBinding(this, exactBinding);
1297                                                                                         this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
1298                                                                                         return variableBinding2;
1299                                                                                 }
1300                                                                         }
1301                                                                         break;
1302                                                         }
1303                                                 }
1304                                         }
1305                                 }
1306                         }
1307                 } else if (node instanceof QualifiedSuperReference) {
1308                         QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
1309                         return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
1310                 } else if (node instanceof LocalDeclaration) {
1311                         return this.getVariableBinding(((LocalDeclaration)node).binding);
1312                 } else if (node instanceof JavadocFieldReference) {
1313                         JavadocFieldReference fieldRef = (JavadocFieldReference) node;
1314                         if (fieldRef.methodBinding != null) {
1315                                 return getMethodBinding(fieldRef.methodBinding);
1316                         }
1317                         return getVariableBinding(fieldRef.binding);
1318                 } else if (node instanceof FieldReference) {
1319                         return getVariableBinding(((FieldReference) node).binding);
1320                 } else if (node instanceof SingleTypeReference) {
1321                         if (node instanceof JavadocSingleTypeReference) {
1322                                 JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) node;
1323                                 if (typeRef.packageBinding != null) {
1324                                         return getPackageBinding(typeRef.packageBinding);
1325                                 }
1326                         }                       
1327                         SingleTypeReference singleTypeReference = (SingleTypeReference) node;
1328                         net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
1329                         if (binding == null) {
1330                                 return null;
1331                         }
1332                         return this.getTypeBinding(binding.leafComponentType());
1333                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
1334                         net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
1335                         return this.getVariableBinding(fieldDeclaration.binding);
1336                 } else if (node instanceof MessageSend) {
1337                         MessageSend messageSend = (MessageSend) node;
1338                         return getMethodBinding(messageSend.binding);
1339                 } else if (node instanceof AllocationExpression) {
1340                         AllocationExpression allocation = (AllocationExpression) node;
1341                         return getMethodBinding(allocation.binding);
1342                 } else if (node instanceof JavadocImplicitTypeReference) {
1343                         JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
1344                         return getTypeBinding(implicitRef.resolvedType);
1345                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) {
1346                         net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter = (net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) node;
1347                         return this.getTypeBinding(typeParameter.binding);
1348                 } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) {
1349                         net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair memberValuePair = (net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) node;
1350                         return getMethodBinding(memberValuePair.binding);
1351                 }
1352                 return null;
1353         }
1354
1355         /*
1356          * @see BindingResolver#resolvePackage(PackageDeclaration)
1357          */
1358         synchronized IPackageBinding resolvePackage(PackageDeclaration pkg) {
1359                 if (this.scope == null) return null;
1360                 try {
1361                         net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(pkg);
1362                         if (node instanceof ImportReference) {
1363                                 ImportReference importReference = (ImportReference) node;
1364                                 Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
1365                                 if ((binding != null) && (binding.isValidBinding())) {
1366                                         if (binding instanceof ReferenceBinding) {
1367                                                 // this only happens if a type name has the same name as its package
1368                                                 ReferenceBinding referenceBinding = (ReferenceBinding) binding;
1369                                                 binding = referenceBinding.fPackage;
1370                                         }
1371                                         if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
1372                                                 IPackageBinding packageBinding = this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) binding);
1373                                                 if (packageBinding == null) {
1374                                                         return null;
1375                                                 }
1376                                                 this.bindingsToAstNodes.put(packageBinding, pkg);
1377                                                 String key = packageBinding.getKey();
1378                                                 if (key != null) {
1379                                                         this.bindingTables.bindingKeysToBindings.put(key, packageBinding);
1380                                                 }
1381                                                 return packageBinding;
1382                                         }
1383                                 }
1384                         }
1385                 } catch (AbortCompilation e) {
1386                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
1387                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
1388                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
1389                 }
1390                 return null;
1391         }
1392
1393         /* (non-Javadoc)
1394          * @see BindingResolver#resolveReference(MemberRef)
1395      * @since 3.0
1396          */
1397         synchronized IBinding resolveReference(MemberRef ref) {
1398                 net.sourceforge.phpdt.internal.compiler.ast.Expression expression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
1399                 if (expression instanceof TypeReference) {
1400                         return getTypeBinding(expression.resolvedType);
1401                 }
1402                 else if (expression instanceof JavadocFieldReference) {
1403                         JavadocFieldReference fieldRef = (JavadocFieldReference) expression;
1404                         if (fieldRef.methodBinding != null) {
1405                                 return getMethodBinding(fieldRef.methodBinding);
1406                         }
1407                         return getVariableBinding(fieldRef.binding);
1408                 }
1409                 return null;
1410         }
1411
1412         /* (non-Javadoc)
1413          * @see BindingResolver#resolveMemberValuePair(MemberValuePair)
1414      * @since 3.2
1415          */
1416         synchronized IMemberValuePairBinding resolveMemberValuePair(net.sourceforge.phpdt.core.dom.MemberValuePair memberValuePair) {
1417                 MemberValuePair valuePair = (MemberValuePair) this.newAstToOldAst.get(memberValuePair);
1418                 return getMemberValuePairBinding(valuePair.compilerElementPair);
1419         }
1420
1421         /* (non-Javadoc)
1422          * @see BindingResolver#resolveReference(MethodRef)
1423      * @since 3.0
1424          */
1425         synchronized IBinding resolveReference(MethodRef ref) {
1426                 net.sourceforge.phpdt.internal.compiler.ast.Expression expression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
1427                 if (expression instanceof JavadocMessageSend) {
1428                         return this.getMethodBinding(((JavadocMessageSend)expression).binding);
1429                 }
1430                 else if (expression instanceof JavadocAllocationExpression) {
1431                         return this.getMethodBinding(((JavadocAllocationExpression)expression).binding);
1432                 }
1433                 return null;
1434         }
1435
1436         /* (non-Javadoc)
1437          * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
1438          */
1439         ITypeBinding resolveType(AnnotationTypeDeclaration type) {
1440                 final Object node = this.newAstToOldAst.get(type);
1441                 if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
1442                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
1443                         ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
1444                         if (typeBinding == null) {
1445                                 return null;
1446                         }
1447                         this.bindingsToAstNodes.put(typeBinding, type);
1448                         String key = typeBinding.getKey();
1449                         if (key != null) {
1450                                 this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
1451                         }
1452                         return typeBinding;
1453                 }
1454                 return null;
1455         }
1456         /*
1457          * @see BindingResolver#resolveType(AnonymousClassDeclaration)
1458          */
1459         synchronized ITypeBinding resolveType(AnonymousClassDeclaration type) {
1460                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
1461                 if (node != null && (node.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
1462                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
1463                         ITypeBinding typeBinding = this.getTypeBinding(anonymousLocalTypeDeclaration.binding);
1464                         if (typeBinding == null) {
1465                                 return null;
1466                         }
1467                         this.bindingsToAstNodes.put(typeBinding, type);
1468                         String key = typeBinding.getKey();
1469                         if (key != null) {
1470                                 this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
1471                         }
1472                         return typeBinding;
1473                 }
1474                 return null;
1475         }
1476
1477         /* (non-Javadoc)
1478          * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.EnumDeclaration)
1479          */
1480         ITypeBinding resolveType(EnumDeclaration type) {
1481                 final Object node = this.newAstToOldAst.get(type);
1482                 if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
1483                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
1484                         ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
1485                         if (typeBinding == null) {
1486                                 return null;
1487                         }
1488                         this.bindingsToAstNodes.put(typeBinding, type);
1489                         String key = typeBinding.getKey();
1490                         if (key != null) {
1491                                 this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
1492                         }
1493                         return typeBinding;
1494                 }
1495                 return null;
1496         }
1497
1498         /*
1499          * Method declared on BindingResolver.
1500          */
1501         synchronized ITypeBinding resolveType(Type type) {
1502                 // retrieve the old ast node
1503                 net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
1504                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding = null;
1505                 if (node != null) {
1506             if (node instanceof ParameterizedQualifiedTypeReference) {
1507                                 ParameterizedQualifiedTypeReference typeReference = (ParameterizedQualifiedTypeReference) node;
1508                                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding = typeReference.resolvedType;
1509                                 int index;
1510                                 if (type.isQualifiedType()) {
1511                                         index = ((QualifiedType) type).index;
1512                                 } else if (type.isParameterizedType()) {
1513                                         index = ((ParameterizedType) type).index;
1514                                 } else {
1515                                         index = 1;
1516                                 }
1517                                 final int numberOfTypeArgumentsNotNull = getTypeArguments(typeReference);
1518                                 if (index != numberOfTypeArgumentsNotNull) {
1519                                         int  i = numberOfTypeArgumentsNotNull;
1520                                         while (i != index) {
1521                                                 typeBinding = typeBinding.enclosingType();
1522                                                 i --;
1523                                         }
1524                                         binding = typeBinding;
1525                                 } else {
1526                                         binding = typeBinding;
1527                                 }
1528             } else if (node instanceof TypeReference) {
1529                                 TypeReference typeReference = (TypeReference) node;
1530                                 binding = typeReference.resolvedType;
1531                         } else if (node instanceof SingleNameReference && ((SingleNameReference)node).isTypeReference()) {
1532                                 binding = (((SingleNameReference)node).resolvedType);
1533                         } else if (node instanceof QualifiedNameReference && ((QualifiedNameReference)node).isTypeReference()) {
1534                                 binding = (((QualifiedNameReference)node).resolvedType);
1535                         } else if (node instanceof ArrayAllocationExpression) {
1536                                 binding = ((ArrayAllocationExpression) node).resolvedType;
1537                         }
1538                         if (binding != null) {
1539                                 if (type.isArrayType()) {
1540                                         ArrayType arrayType = (ArrayType) type;
1541                                         if (this.scope == null) return null;
1542                                         if (binding.isArrayType()) {
1543                                                 ArrayBinding arrayBinding = (ArrayBinding) binding;
1544                                                 return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
1545                                         } else {
1546                                                 return getTypeBinding(this.scope.createArrayType(binding, arrayType.getDimensions()));
1547                                         }
1548                                 } else {
1549                                         if (binding.isArrayType()) {
1550                                                 ArrayBinding arrayBinding = (ArrayBinding) binding;
1551                                                 return getTypeBinding(arrayBinding.leafComponentType);
1552                                         } else {
1553                                                 return getTypeBinding(binding);
1554                                         }
1555                                 }
1556                         }
1557                 } else if (type.isPrimitiveType()) {
1558                         /* Handle the void primitive type returned by getReturnType for a method declaration
1559                          * that is a constructor declaration. It prevents null from being returned
1560                          */
1561                         if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
1562                                 return this.getTypeBinding(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.VOID);
1563                         }
1564                 }
1565                 return null;
1566         }
1567
1568         /*
1569          * Method declared on BindingResolver.
1570          */
1571         synchronized ITypeBinding resolveType(TypeDeclaration type) {
1572                 final Object node = this.newAstToOldAst.get(type);
1573                 if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
1574                         net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
1575                         ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
1576                         if (typeBinding == null) {
1577                                 return null;
1578                         }
1579                         this.bindingsToAstNodes.put(typeBinding, type);
1580                         String key = typeBinding.getKey();
1581                         if (key != null) {
1582                                 this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
1583                         }
1584                         return typeBinding;
1585                 }
1586                 return null;
1587         }
1588
1589         synchronized ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
1590                 final Object node = this.newAstToOldAst.get(typeParameter);
1591                 if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) {
1592                         net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter2 = (net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) node;
1593                         ITypeBinding typeBinding = this.getTypeBinding(typeParameter2.binding);
1594                         if (typeBinding == null) {
1595                                 return null;
1596                         }
1597                         this.bindingsToAstNodes.put(typeBinding, typeParameter);
1598                         String key = typeBinding.getKey();
1599                         if (key != null) {
1600                                 this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
1601                         }
1602                         return typeBinding;
1603                 }
1604                 return null;
1605         }
1606
1607         /* (non-Javadoc)
1608          * @see org.eclipse.jdt.core.dom.BindingResolver#resolveVariable(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
1609          */
1610         synchronized IVariableBinding resolveVariable(EnumConstantDeclaration enumConstant) {
1611                 final Object node = this.newAstToOldAst.get(enumConstant);
1612                 if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
1613                         net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
1614                         IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
1615                         if (variableBinding == null) {
1616                                 return null;
1617                         }
1618                         this.bindingsToAstNodes.put(variableBinding, enumConstant);
1619                         String key = variableBinding.getKey();
1620                         if (key != null) {
1621                                 this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
1622                         }
1623                         return variableBinding;
1624                 }
1625                 return null;
1626         }
1627         /*
1628          * Method declared on BindingResolver.
1629          */
1630         synchronized IVariableBinding resolveVariable(VariableDeclaration variable) {
1631                 final Object node = this.newAstToOldAst.get(variable);
1632                 if (node instanceof AbstractVariableDeclaration) {
1633                         AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
1634                         IVariableBinding variableBinding = null;
1635                         if (abstractVariableDeclaration instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
1636                                 net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
1637                                 variableBinding = this.getVariableBinding(fieldDeclaration.binding, variable);
1638                         } else {
1639                                 variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding, variable);
1640                         }
1641                         if (variableBinding == null) {
1642                                 return null;
1643                         }
1644                         this.bindingsToAstNodes.put(variableBinding, variable);
1645                         String key = variableBinding.getKey();
1646                         if (key != null) {
1647                                 this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
1648                         }
1649                         return variableBinding;
1650                 }
1651                 return null;
1652         }
1653
1654         /*
1655          * Method declared on BindingResolver.
1656          */
1657         synchronized ITypeBinding resolveWellKnownType(String name) {
1658                 if (this.scope == null) return null;
1659                 try {
1660                         if (("boolean".equals(name))//$NON-NLS-1$
1661                                 || ("char".equals(name))//$NON-NLS-1$
1662                                 || ("byte".equals(name))//$NON-NLS-1$
1663                                 || ("short".equals(name))//$NON-NLS-1$
1664                                 || ("int".equals(name))//$NON-NLS-1$
1665                                 || ("long".equals(name))//$NON-NLS-1$
1666                                 || ("float".equals(name))//$NON-NLS-1$
1667                                 || ("double".equals(name))//$NON-NLS-1$
1668                                 || ("void".equals(name))) {//$NON-NLS-1$
1669                                 return this.getTypeBinding(Scope.getBaseType(name.toCharArray()));
1670                         } else if ("java.lang.Object".equals(name)) {//$NON-NLS-1$
1671                                 return this.getTypeBinding(this.scope.getJavaLangObject());
1672                         } else if ("java.lang.String".equals(name)) {//$NON-NLS-1$
1673                                 return this.getTypeBinding(this.scope.getJavaLangString());
1674                         } else if ("java.lang.StringBuffer".equals(name)) {//$NON-NLS-1$
1675                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_STRINGBUFFER, 3));
1676                         } else if ("java.lang.Throwable".equals(name)) {//$NON-NLS-1$
1677                                 return this.getTypeBinding(this.scope.getJavaLangThrowable());
1678                         } else if ("java.lang.Exception".equals(name)) {//$NON-NLS-1$
1679                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_EXCEPTION, 3));
1680                         } else if ("java.lang.RuntimeException".equals(name)) {//$NON-NLS-1$
1681                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3));
1682                         } else if ("java.lang.Error".equals(name)) {//$NON-NLS-1$
1683                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_ERROR, 3));
1684                         } else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$
1685                                 return this.getTypeBinding(this.scope.getJavaLangClass());
1686                         } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$
1687                                 return this.getTypeBinding(this.scope.getJavaLangCloneable());
1688                         } else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$
1689                                 return this.getTypeBinding(this.scope.getJavaIoSerializable());
1690                         } else if ("java.lang.Boolean".equals(name)) {//$NON-NLS-1$
1691                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BOOLEAN, 3));
1692                         } else if ("java.lang.Byte".equals(name)) {//$NON-NLS-1$
1693                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BYTE, 3));
1694                         } else if ("java.lang.Character".equals(name)) {//$NON-NLS-1$
1695                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_CHARACTER, 3));
1696                         } else if ("java.lang.Double".equals(name)) {//$NON-NLS-1$
1697                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_DOUBLE, 3));
1698                         } else if ("java.lang.Float".equals(name)) {//$NON-NLS-1$
1699                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_FLOAT, 3));
1700                         } else if ("java.lang.Integer".equals(name)) {//$NON-NLS-1$
1701                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_INTEGER, 3));
1702                         } else if ("java.lang.Long".equals(name)) {//$NON-NLS-1$
1703                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_LONG, 3));
1704                         } else if ("java.lang.Short".equals(name)) {//$NON-NLS-1$
1705                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_SHORT, 3));
1706                         } else if ("java.lang.Void".equals(name)) {//$NON-NLS-1$
1707                                 return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_VOID, 3));
1708                         }
1709                 } catch (AbortCompilation e) {
1710                         // ignore missing types
1711                 }
1712                 return null;
1713         }
1714
1715         synchronized IAnnotationBinding resolveAnnotation(final Annotation domASTNode) {
1716                 Object oldNode = this.newAstToOldAst.get(domASTNode);
1717                 if (oldNode instanceof net.sourceforge.phpdt.internal.compiler.ast.Annotation) {
1718                         net.sourceforge.phpdt.internal.compiler.ast.Annotation internalAstNode =
1719                                 (net.sourceforge.phpdt.internal.compiler.ast.Annotation) oldNode;
1720
1721                         IAnnotationBinding domAnnotation = this.getAnnotationInstance(internalAstNode.getCompilerAnnotation());
1722                         if (domAnnotation == null)
1723                                 return null;
1724                         this.bindingsToAstNodes.put(domAnnotation, domASTNode);
1725                         return domAnnotation;
1726                 }
1727                 return null;
1728         }
1729
1730         /*
1731          * Method declared on BindingResolver.
1732          */
1733         public CompilationUnitScope scope() {
1734                 return this.scope;
1735         }
1736
1737         /*
1738          * Method declared on BindingResolver.
1739          */
1740         synchronized void store(ASTNode node, net.sourceforge.phpdt.internal.compiler.ast.ASTNode oldASTNode) {
1741                 this.newAstToOldAst.put(node, oldASTNode);
1742         }
1743
1744         /*
1745          * Method declared on BindingResolver.
1746          */
1747         synchronized void updateKey(ASTNode node, ASTNode newNode) {
1748                 Object astNode = this.newAstToOldAst.remove(node);
1749                 if (astNode != null) {
1750                         this.newAstToOldAst.put(newNode, astNode);
1751                 }
1752         }
1753
1754         /**
1755          * Answer an array type binding with the given type binding and the given
1756          * dimensions.
1757          *
1758          * <p>If the given type binding is an array binding, then the resulting dimensions is the given dimensions
1759          * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
1760          * dimensions.</p>
1761          *
1762          * <p>
1763          * The default implementation of this method returns <code>null</code>.
1764          * Subclasses may reimplement.
1765          * </p>
1766          *
1767          * @param typeBinding the given type binding
1768          * @param dimensions the given dimensions
1769          * @return an array type binding with the given type binding and the given
1770          * dimensions
1771          * @throws IllegalArgumentException if the type binding represents the <code>void</code> type binding
1772          */
1773         ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
1774                 if (typeBinding instanceof RecoveredTypeBinding) throw new IllegalArgumentException("Cannot be called on a recovered type binding"); //$NON-NLS-1$
1775                 ITypeBinding leafComponentType = typeBinding;
1776                 int actualDimensions = dimensions;
1777                 if (typeBinding.isArray()) {
1778                         leafComponentType = typeBinding.getElementType();
1779                         actualDimensions += typeBinding.getDimensions();
1780                 }
1781                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding leafTypeBinding = null;
1782                 if (leafComponentType.isPrimitive()) {
1783                         String name = leafComponentType.getBinaryName();
1784                         switch(name.charAt(0)) {
1785                                 case 'I' :
1786                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.INT;
1787                                         break;
1788                                 case 'B' :
1789                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.BYTE;
1790                                         break;
1791                                 case 'Z' :
1792                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.BOOLEAN;
1793                                         break;
1794                                 case 'C' :
1795                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.CHAR;
1796                                         break;
1797                                 case 'J' :
1798                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.LONG;
1799                                         break;
1800                                 case 'S' :
1801                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.SHORT;
1802                                         break;
1803                                 case 'D' :
1804                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.DOUBLE;
1805                                         break;
1806                                 case 'F' :
1807                                         leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.FLOAT;
1808                                         break;
1809                                 case 'V' :
1810                                         throw new IllegalArgumentException();
1811                         }
1812                 } else {
1813                         if (!(leafComponentType instanceof TypeBinding)) return null;
1814                         leafTypeBinding = ((TypeBinding) leafComponentType).binding;
1815                 }
1816                 return this.getTypeBinding(this.lookupEnvironment().createArrayType(leafTypeBinding, actualDimensions));
1817         }
1818 }