update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / impl / source / tree / java / PsiNewExpressionImpl.java
blob379787a85ad1febc1b95525622a1e9f19718c13a
1 /*
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(){
46 PsiType type = null;
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());
52 continue;
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);
77 return type;
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);
87 return null;
90 @NotNull
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){
95 return expressions;
97 else{
98 LOG.assertTrue(expressions[0] == qualifier);
99 PsiExpression[] expressions1 = new PsiExpression[expressions.length - 1];
100 System.arraycopy(expressions, 1, expressions1, 0, expressions1.length);
101 return expressions1;
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() {
115 @NotNull
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);
128 else{
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),
137 anonymousClass);
140 return JavaResolveResult.EMPTY_ARRAY;
143 public PsiElement getElement() {
144 return PsiNewExpressionImpl.this;
147 public TextRange getRangeInElement() {
148 return null;
151 public String getCanonicalText() {
152 return null;
155 public PsiElement handleElementRename(String newElementName) {
156 return null;
159 public PsiElement bindToElement(@NotNull PsiElement element) {
160 return null;
163 public Object[] getVariants() {
164 return ArrayUtil.EMPTY_OBJECT_ARRAY;
167 @Override
168 public int hashCode() {
169 PsiJavaCodeReferenceElement ref = getClassOrAnonymousClassReference();
170 return ref == null ? 0 : ref.hashCode();
173 @Override
174 public boolean equals(Object obj) {
175 return obj instanceof PsiPolyVariantCachingReference && getElement() == ((PsiReference)obj).getElement();
180 @NotNull
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);
190 @NotNull
191 public PsiReferenceParameterList getTypeArgumentList() {
192 return (PsiReferenceParameterList) findChildByRoleAsPsiElement(ChildRole.REFERENCE_PARAMETER_LIST);
195 @NotNull
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);
215 @Nullable
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);
230 else{
231 super.deleteChildInternal(child);
235 public ASTNode findChildByRole(int role){
236 LOG.assertTrue(ChildRole.isUnique(role));
237 switch(role){
238 default:
239 return null;
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) {
247 return firstChild;
249 else {
250 return null;
253 case ChildRole.DOT:
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();
281 else{
282 return null;
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;
318 else {
319 return ChildRole.ARRAY_DIMENSION;
322 else if (i == JavaElementType.ANONYMOUS_CLASS) {
323 return ChildRole.ANONYMOUS_CLASS;
325 else {
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;
332 else {
333 return ChildRoleBase.NONE;
338 public void accept(@NotNull PsiElementVisitor visitor){
339 if (visitor instanceof JavaElementVisitor) {
340 ((JavaElementVisitor)visitor).visitNewExpression(this);
342 else {
343 visitor.visitElement(this);
347 public String toString(){
348 return "PsiNewExpression:" + getText();