1/*
2 * Copyright 2014, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32package org.jf.smalidea.psi.impl;
33
34import com.intellij.openapi.util.TextRange;
35import com.intellij.psi.*;
36import com.intellij.psi.impl.light.LightElement;
37import com.intellij.psi.infos.CandidateInfo;
38import com.intellij.psi.scope.PsiScopeProcessor;
39import com.intellij.util.IncorrectOperationException;
40import org.jetbrains.annotations.NonNls;
41import org.jetbrains.annotations.NotNull;
42import org.jetbrains.annotations.Nullable;
43import org.jf.smalidea.SmaliLanguage;
44import org.jf.smalidea.util.NameUtils;
45
46public class LightSmaliClassTypeElement extends LightElement
47        implements PsiTypeElement, PsiReference, PsiJavaCodeReferenceElement {
48    @NotNull
49    private final String smaliName;
50
51    public LightSmaliClassTypeElement(@NotNull PsiManager manager, @NotNull String smaliName) {
52        super(manager, SmaliLanguage.INSTANCE);
53        this.smaliName = smaliName;
54    }
55
56    @Override public String toString() {
57        return "LightSmaliClassTypeElement:" + smaliName;
58    }
59
60    @NotNull @Override public PsiType getType() {
61        return new SmaliClassType(this);
62    }
63
64    @Nullable @Override public LightSmaliClassTypeElement getInnermostComponentReferenceElement() {
65        return this;
66    }
67
68    @Override public String getText() {
69        return smaliName;
70    }
71
72    @Override public PsiReference getReference() {
73        return this;
74    }
75
76    @Override public PsiElement getElement() {
77        return this;
78    }
79
80    @Override public TextRange getRangeInElement() {
81        return new TextRange(0, getTextLength());
82    }
83
84    @Nullable @Override public PsiClass resolve() {
85        return NameUtils.resolveSmaliType(this, smaliName);
86    }
87
88    @NotNull @Override public String getCanonicalText() {
89        return NameUtils.resolveSmaliToJavaType(this, smaliName);
90    }
91
92    @Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
93        throw new UnsupportedOperationException();
94    }
95
96    @Override public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
97        throw new UnsupportedOperationException();
98    }
99
100    @Override public boolean isReferenceTo(PsiElement element) {
101        if (!(element instanceof PsiClassType)) {
102            return false;
103        }
104        return element.getManager().areElementsEquivalent(element, resolve());
105    }
106
107    @NotNull @Override public Object[] getVariants() {
108        throw new RuntimeException("Variants are not available for light references");
109    }
110
111    @Override public boolean isSoft() {
112        return false;
113    }
114
115    @NotNull @Override public PsiAnnotation[] getAnnotations() {
116        return new PsiAnnotation[0];
117    }
118
119    @NotNull @Override public PsiAnnotation[] getApplicableAnnotations() {
120        return new PsiAnnotation[0];
121    }
122
123    @Nullable @Override public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
124        return null;
125    }
126
127    @NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
128        throw new UnsupportedOperationException();
129    }
130
131    // ***************************************************************************
132    // Below are the PsiJavaCodeReferenceElement-specific methods
133
134    @Override public void processVariants(@NotNull PsiScopeProcessor processor) {
135        // TODO: maybe just do nothing?
136        throw new UnsupportedOperationException();
137    }
138
139    @Nullable @Override public PsiElement getReferenceNameElement() {
140        // TODO: implement if needed
141        throw new UnsupportedOperationException();
142    }
143
144    @Nullable @Override public PsiReferenceParameterList getParameterList() {
145        // TODO: (generics) implement this
146        return null;
147    }
148
149    @NotNull @Override public PsiType[] getTypeParameters() {
150        // TODO: (generics) implement this
151        return new PsiType[0];
152    }
153
154    @Override public boolean isQualified() {
155        // TODO: should this return false for classes in the top level package?
156        return true;
157    }
158
159    @Override public String getQualifiedName() {
160        return getCanonicalText();
161    }
162
163    @NotNull @Override public JavaResolveResult advancedResolve(boolean incompleteCode) {
164        PsiClass element = resolve();
165        if (element == null) {
166            return JavaResolveResult.EMPTY;
167        }
168        return new CandidateInfo(element, PsiSubstitutor.EMPTY);
169    }
170
171    @NotNull @Override public JavaResolveResult[] multiResolve(boolean incompleteCode) {
172        PsiClass element = resolve();
173        if (element == null) {
174            return JavaResolveResult.EMPTY_ARRAY;
175        }
176        return new CandidateInfo[] { new CandidateInfo(element, PsiSubstitutor.EMPTY) };
177    }
178
179    @Nullable @Override public PsiElement getQualifier() {
180        // TODO: implement this if needed
181        throw new UnsupportedOperationException();
182    }
183
184    @Nullable @Override public String getReferenceName() {
185        return getName();
186    }
187}
188