2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.psi
.impl
.source
.tree
.java
;
18 import com
.intellij
.lang
.ASTNode
;
19 import com
.intellij
.openapi
.diagnostic
.Logger
;
20 import com
.intellij
.openapi
.util
.TextRange
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.psi
.impl
.source
.Constants
;
23 import com
.intellij
.psi
.impl
.source
.PsiClassReferenceType
;
24 import com
.intellij
.psi
.impl
.source
.SourceTreeToPsiMap
;
25 import com
.intellij
.psi
.impl
.source
.resolve
.reference
.impl
.PsiPolyVariantCachingReference
;
26 import com
.intellij
.psi
.impl
.source
.tree
.*;
27 import com
.intellij
.psi
.tree
.ChildRoleBase
;
28 import com
.intellij
.psi
.tree
.IElementType
;
29 import com
.intellij
.psi
.tree
.TokenSet
;
30 import com
.intellij
.psi
.util
.PsiUtil
;
31 import com
.intellij
.util
.ArrayUtil
;
32 import com
.intellij
.util
.SmartList
;
33 import org
.jetbrains
.annotations
.NotNull
;
34 import org
.jetbrains
.annotations
.Nullable
;
36 import java
.util
.List
;
38 public class PsiNewExpressionImpl
extends ExpressionPsiElement
implements PsiNewExpression
{
39 private static final Logger LOG
= Logger
.getInstance("#com.intellij.psi.impl.source.tree.java.PsiNewExpressionImpl");
41 public PsiNewExpressionImpl() {
42 super(JavaElementType
.NEW_EXPRESSION
);
45 public PsiType
getType(){
47 List
<PsiAnnotation
> annotations
= new SmartList
<PsiAnnotation
>();
48 for(ASTNode child
= getFirstChildNode(); child
!= null; child
= child
.getTreeNext()){
49 IElementType elementType
= child
.getElementType();
50 if (elementType
== JavaElementType
.ANNOTATION
) {
51 annotations
.add((PsiAnnotation
)child
.getPsi());
54 if (elementType
== JavaElementType
.JAVA_CODE_REFERENCE
){
55 LOG
.assertTrue(type
== null);
56 type
= new PsiClassReferenceType((PsiJavaCodeReferenceElement
)SourceTreeToPsiMap
.treeElementToPsi(child
), null);
58 else if (ElementType
.PRIMITIVE_TYPE_BIT_SET
.contains(elementType
)){
59 LOG
.assertTrue(type
== null);
60 PsiAnnotation
[] annos
= annotations
.toArray(new PsiAnnotation
[annotations
.size()]);
61 type
= JavaPsiFacade
.getInstance(getProject()).getElementFactory().createPrimitiveType(child
.getText(), annos
);
63 else if (elementType
== JavaTokenType
.LBRACKET
){
64 LOG
.assertTrue(type
!= null);
65 PsiAnnotation
[] annos
= annotations
.toArray(new PsiAnnotation
[annotations
.size()]);
67 type
= type
.createArrayType(annos
);
69 else if (elementType
== JavaElementType
.ANONYMOUS_CLASS
){
70 PsiAnnotation
[] annos
= annotations
.toArray(new PsiAnnotation
[annotations
.size()]);
71 PsiElementFactory factory
= JavaPsiFacade
.getInstance(getProject()).getElementFactory();
72 PsiClass aClass
= (PsiClass
)SourceTreeToPsiMap
.treeElementToPsi(child
);
73 PsiSubstitutor substitutor
= aClass
instanceof PsiTypeParameter ? PsiSubstitutor
.EMPTY
: factory
.createRawSubstitutor(aClass
);
74 type
= factory
.createType(aClass
, substitutor
, PsiUtil
.getLanguageLevel(aClass
),annos
);
80 public PsiExpressionList
getArgumentList() {
81 PsiExpressionList list
= (PsiExpressionList
)findChildByRoleAsPsiElement(ChildRole
.ARGUMENT_LIST
);
82 if (list
!= null) return list
;
83 CompositeElement anonymousClass
= (CompositeElement
)SourceTreeToPsiMap
.psiElementToTree(findChildByRoleAsPsiElement(ChildRole
.ANONYMOUS_CLASS
));
84 if (anonymousClass
!= null){
85 return (PsiExpressionList
)anonymousClass
.findChildByRoleAsPsiElement(ChildRole
.ARGUMENT_LIST
);
91 public PsiExpression
[] getArrayDimensions() {
92 PsiExpression
[] expressions
= getChildrenAsPsiElements(ElementType
.ARRAY_DIMENSION_BIT_SET
, Constants
.PSI_EXPRESSION_ARRAY_CONSTRUCTOR
);
93 PsiExpression qualifier
= getQualifier();
94 if (qualifier
== null){
98 LOG
.assertTrue(expressions
[0] == qualifier
);
99 PsiExpression
[] expressions1
= new PsiExpression
[expressions
.length
- 1];
100 System
.arraycopy(expressions
, 1, expressions1
, 0, expressions1
.length
);
105 public PsiArrayInitializerExpression
getArrayInitializer() {
106 return (PsiArrayInitializerExpression
)findChildByRoleAsPsiElement(ChildRole
.ARRAY_INITIALIZER
);
109 public PsiMethod
resolveMethod() {
110 return resolveConstructor();
113 private PsiPolyVariantCachingReference
getConstructorFakeReference() {
114 return new PsiPolyVariantCachingReference() {
116 public JavaResolveResult
[] resolveInner(boolean incompleteCode
) {
117 ASTNode classRef
= findChildByRole(ChildRole
.TYPE_REFERENCE
);
118 if (classRef
!= null) {
119 ASTNode argumentList
= TreeUtil
.skipElements(classRef
.getTreeNext(), StdTokenSets
.WHITE_SPACE_OR_COMMENT_BIT_SET
);
120 if (argumentList
!= null && argumentList
.getElementType() == JavaElementType
.EXPRESSION_LIST
) {
121 final JavaPsiFacade facade
= JavaPsiFacade
.getInstance(getProject());
122 PsiType aClass
= facade
.getElementFactory().createType((PsiJavaCodeReferenceElement
)SourceTreeToPsiMap
.treeElementToPsi(classRef
));
123 return facade
.getResolveHelper().multiResolveConstructor((PsiClassType
)aClass
,
124 (PsiExpressionList
)SourceTreeToPsiMap
.treeElementToPsi(argumentList
),
125 PsiNewExpressionImpl
.this);
129 ASTNode anonymousClassElement
= findChildByType(JavaElementType
.ANONYMOUS_CLASS
);
130 if (anonymousClassElement
!= null) {
131 final JavaPsiFacade facade
= JavaPsiFacade
.getInstance(getProject());
132 final PsiAnonymousClass anonymousClass
= (PsiAnonymousClass
)SourceTreeToPsiMap
.treeElementToPsi(anonymousClassElement
);
133 PsiType aClass
= anonymousClass
.getBaseClassType();
134 ASTNode argumentList
= anonymousClassElement
.findChildByType(JavaElementType
.EXPRESSION_LIST
);
135 return facade
.getResolveHelper().multiResolveConstructor((PsiClassType
)aClass
,
136 (PsiExpressionList
)SourceTreeToPsiMap
.treeElementToPsi(argumentList
),
140 return JavaResolveResult
.EMPTY_ARRAY
;
143 public PsiElement
getElement() {
144 return PsiNewExpressionImpl
.this;
147 public TextRange
getRangeInElement() {
151 public String
getCanonicalText() {
155 public PsiElement
handleElementRename(String newElementName
) {
159 public PsiElement
bindToElement(@NotNull PsiElement element
) {
163 public Object
[] getVariants() {
164 return ArrayUtil
.EMPTY_OBJECT_ARRAY
;
168 public int hashCode() {
169 PsiJavaCodeReferenceElement ref
= getClassOrAnonymousClassReference();
170 return ref
== null ?
0 : ref
.hashCode();
174 public boolean equals(Object obj
) {
175 return obj
instanceof PsiPolyVariantCachingReference
&& getElement() == ((PsiReference
)obj
).getElement();
181 public JavaResolveResult
resolveMethodGenerics() {
182 ResolveResult
[] results
= getConstructorFakeReference().multiResolve(false);
183 return results
.length
== 1 ?
(JavaResolveResult
)results
[0] : JavaResolveResult
.EMPTY
;
186 public PsiExpression
getQualifier() {
187 return (PsiExpression
)findChildByRoleAsPsiElement(ChildRole
.QUALIFIER
);
191 public PsiReferenceParameterList
getTypeArgumentList() {
192 return (PsiReferenceParameterList
) findChildByRoleAsPsiElement(ChildRole
.REFERENCE_PARAMETER_LIST
);
196 public PsiType
[] getTypeArguments() {
197 return getTypeArgumentList().getTypeArguments();
200 public PsiMethod
resolveConstructor(){
201 return (PsiMethod
)resolveMethodGenerics().getElement();
204 public PsiJavaCodeReferenceElement
getClassReference() {
205 return (PsiJavaCodeReferenceElement
)findChildByRoleAsPsiElement(ChildRole
.TYPE_REFERENCE
);
208 public PsiAnonymousClass
getAnonymousClass() {
209 ASTNode anonymousClass
= findChildByType(JavaElementType
.ANONYMOUS_CLASS
);
210 if (anonymousClass
== null) return null;
211 return (PsiAnonymousClass
)SourceTreeToPsiMap
.treeElementToPsi(anonymousClass
);
214 private static final TokenSet CLASS_REF
= TokenSet
.create(JavaElementType
.JAVA_CODE_REFERENCE
, JavaElementType
.ANONYMOUS_CLASS
);
216 public PsiJavaCodeReferenceElement
getClassOrAnonymousClassReference() {
217 ASTNode ref
= findChildByType(CLASS_REF
);
218 if (ref
== null) return null;
219 if (ref
instanceof PsiJavaCodeReferenceElement
) return (PsiJavaCodeReferenceElement
)ref
;
220 PsiAnonymousClass anonymousClass
= (PsiAnonymousClass
)ref
.getPsi();
221 return anonymousClass
.getBaseClassReference();
224 public void deleteChildInternal(@NotNull ASTNode child
) {
225 if (getChildRole(child
) == ChildRole
.QUALIFIER
){
226 ASTNode dot
= findChildByRole(ChildRole
.DOT
);
227 super.deleteChildInternal(child
);
228 deleteChildInternal(dot
);
231 super.deleteChildInternal(child
);
235 public ASTNode
findChildByRole(int role
){
236 LOG
.assertTrue(ChildRole
.isUnique(role
));
241 case ChildRole
.REFERENCE_PARAMETER_LIST
:
242 return findChildByType(JavaElementType
.REFERENCE_PARAMETER_LIST
);
244 case ChildRole
.QUALIFIER
:
245 TreeElement firstChild
= getFirstChildNode();
246 if (firstChild
!= null && firstChild
.getElementType() != JavaTokenType
.NEW_KEYWORD
) {
254 return findChildByType(JavaTokenType
.DOT
);
256 case ChildRole
.NEW_KEYWORD
:
257 return findChildByType(JavaTokenType
.NEW_KEYWORD
);
259 case ChildRole
.ANONYMOUS_CLASS
:
260 return findChildByType(JavaElementType
.ANONYMOUS_CLASS
);
262 case ChildRole
.TYPE_REFERENCE
:
263 return findChildByType(JavaElementType
.JAVA_CODE_REFERENCE
);
265 case ChildRole
.TYPE_KEYWORD
:
266 return findChildByType(ElementType
.PRIMITIVE_TYPE_BIT_SET
);
268 case ChildRole
.ARGUMENT_LIST
:
269 return findChildByType(JavaElementType
.EXPRESSION_LIST
);
271 case ChildRole
.LBRACKET
:
272 return findChildByType(JavaTokenType
.LBRACKET
);
274 case ChildRole
.RBRACKET
:
275 return findChildByType(JavaTokenType
.RBRACKET
);
277 case ChildRole
.ARRAY_INITIALIZER
:
278 if (getLastChildNode().getElementType() == JavaElementType
.ARRAY_INITIALIZER_EXPRESSION
){
279 return getLastChildNode();
287 public int getChildRole(ASTNode child
) {
288 LOG
.assertTrue(child
.getTreeParent() == this);
289 IElementType i
= child
.getElementType();
290 if (i
== JavaElementType
.REFERENCE_PARAMETER_LIST
) {
291 return ChildRole
.REFERENCE_PARAMETER_LIST
;
293 else if (i
== JavaTokenType
.NEW_KEYWORD
) {
294 return ChildRole
.NEW_KEYWORD
;
296 else if (i
== JavaTokenType
.DOT
) {
297 return ChildRole
.DOT
;
299 else if (i
== JavaElementType
.JAVA_CODE_REFERENCE
) {
300 return ChildRole
.TYPE_REFERENCE
;
302 else if (i
== JavaElementType
.EXPRESSION_LIST
) {
303 return ChildRole
.ARGUMENT_LIST
;
305 else if (i
== JavaTokenType
.LBRACKET
) {
306 return ChildRole
.LBRACKET
;
308 else if (i
== JavaTokenType
.RBRACKET
) {
309 return ChildRole
.RBRACKET
;
311 else if (i
== JavaElementType
.ARRAY_INITIALIZER_EXPRESSION
) {
312 if (child
== getLastChildNode()) {
313 return ChildRole
.ARRAY_INITIALIZER
;
315 else if (child
== getFirstChildNode()) {
316 return ChildRole
.QUALIFIER
;
319 return ChildRole
.ARRAY_DIMENSION
;
322 else if (i
== JavaElementType
.ANONYMOUS_CLASS
) {
323 return ChildRole
.ANONYMOUS_CLASS
;
326 if (ElementType
.PRIMITIVE_TYPE_BIT_SET
.contains(child
.getElementType())) {
327 return ChildRole
.TYPE_KEYWORD
;
329 else if (ElementType
.EXPRESSION_BIT_SET
.contains(child
.getElementType())) {
330 return child
== getFirstChildNode() ? ChildRole
.QUALIFIER
: ChildRole
.ARRAY_DIMENSION
;
333 return ChildRoleBase
.NONE
;
338 public void accept(@NotNull PsiElementVisitor visitor
){
339 if (visitor
instanceof JavaElementVisitor
) {
340 ((JavaElementVisitor
)visitor
).visitNewExpression(this);
343 visitor
.visitElement(this);
347 public String
toString(){
348 return "PsiNewExpression:" + getText();