001    /*
002     * Copyright 2010-2016 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.asJava.builder;
018    
019    import com.intellij.openapi.util.Key;
020    import com.intellij.openapi.util.UserDataHolder;
021    import com.intellij.psi.*;
022    import com.intellij.psi.impl.compiled.ClsClassImpl;
023    import com.intellij.psi.impl.compiled.ClsEnumConstantImpl;
024    import com.intellij.psi.impl.compiled.ClsFieldImpl;
025    import com.intellij.psi.impl.compiled.ClsRepositoryPsiElement;
026    import com.intellij.psi.impl.java.stubs.*;
027    import com.intellij.psi.stubs.StubBase;
028    import com.intellij.psi.stubs.StubElement;
029    import org.jetbrains.annotations.NotNull;
030    import org.jetbrains.annotations.Nullable;
031    
032    public class ClsWrapperStubPsiFactory extends StubPsiFactory {
033        public static final Key<LightElementOrigin> ORIGIN = Key.create("ORIGIN");
034        public static final ClsWrapperStubPsiFactory INSTANCE = new ClsWrapperStubPsiFactory();
035    
036        private final StubPsiFactory delegate = new ClsStubPsiFactory();
037    
038        private ClsWrapperStubPsiFactory() { }
039    
040        @Nullable
041        public static LightMemberOriginForDeclaration getMemberOrigin(@NotNull PsiMember member) {
042            if (member instanceof ClsRepositoryPsiElement<?>) {
043                StubElement stubElement = ((ClsRepositoryPsiElement<?>) member).getStub();
044                if (stubElement instanceof UserDataHolder) {
045                    LightElementOrigin origin = ((UserDataHolder) stubElement).getUserData(ORIGIN);
046                    if (origin instanceof LightMemberOriginForDeclaration) {
047                        return (LightMemberOriginForDeclaration) origin;
048                    }
049                }
050            }
051    
052            return null;
053        }
054    
055        @Override
056        public PsiClass createClass(@NotNull PsiClassStub stub) {
057            final PsiElement origin = getOriginalElement(stub);
058            return new ClsClassImpl(stub) {
059                @NotNull
060                @Override
061                public PsiElement getNavigationElement() {
062                    if (origin != null) return origin;
063    
064                    return super.getNavigationElement();
065                }
066    
067                @Nullable
068                @Override
069                public PsiClass getSourceMirrorClass() {
070                    return null;
071                }
072            };
073        }
074    
075        @Nullable
076        public static PsiElement getOriginalElement(@NotNull StubElement stub) {
077            LightElementOrigin origin = ((StubBase) stub).getUserData(ORIGIN);
078            return origin != null ? origin.getOriginalElement() : null;
079        }
080    
081        @Override
082        public PsiAnnotation createAnnotation(PsiAnnotationStub stub) {
083            return delegate.createAnnotation(stub);
084        }
085    
086        @Override
087        public PsiClassInitializer createClassInitializer(PsiClassInitializerStub stub) {
088            return delegate.createClassInitializer(stub);
089        }
090    
091        @Override
092        public PsiReferenceList createClassReferenceList(PsiClassReferenceListStub stub) {
093            return delegate.createClassReferenceList(stub);
094        }
095    
096        @Override
097        public PsiField createField(PsiFieldStub stub) {
098            final PsiElement origin = getOriginalElement(stub);
099            if (origin == null) return delegate.createField(stub);
100            if (stub.isEnumConstant()) {
101                return new ClsEnumConstantImpl(stub) {
102                    @NotNull
103                    @Override
104                    public PsiElement getNavigationElement() {
105                        return origin;
106                    }
107                };
108            }
109            else {
110                return new ClsFieldImpl(stub) {
111                    @NotNull
112                    @Override
113                    public PsiElement getNavigationElement() {
114                        return origin;
115                    }
116                };
117            }
118        }
119    
120        @Override
121        public PsiImportList createImportList(PsiImportListStub stub) {
122            return delegate.createImportList(stub);
123        }
124    
125        @Override
126        public PsiImportStatementBase createImportStatement(PsiImportStatementStub stub) {
127            return delegate.createImportStatement(stub);
128        }
129    
130        @Override
131        public PsiMethod createMethod(PsiMethodStub stub) {
132            return delegate.createMethod(stub);
133        }
134    
135        @Override
136        public PsiModifierList createModifierList(PsiModifierListStub stub) {
137            return delegate.createModifierList(stub);
138        }
139    
140        @Override
141        public PsiParameter createParameter(PsiParameterStub stub) {
142            return delegate.createParameter(stub);
143        }
144    
145        @Override
146        public PsiParameterList createParameterList(PsiParameterListStub stub) {
147            return delegate.createParameterList(stub);
148        }
149    
150        @Override
151        public PsiTypeParameter createTypeParameter(PsiTypeParameterStub stub) {
152            return delegate.createTypeParameter(stub);
153        }
154    
155        @Override
156        public PsiTypeParameterList createTypeParameterList(PsiTypeParameterListStub stub) {
157            return delegate.createTypeParameterList(stub);
158        }
159    
160        @Override
161        public PsiAnnotationParameterList createAnnotationParameterList(PsiAnnotationParameterListStub stub) {
162            return delegate.createAnnotationParameterList(stub);
163        }
164    
165        @Override
166        public PsiNameValuePair createNameValuePair(PsiNameValuePairStub stub) {
167            return delegate.createNameValuePair(stub);
168        }
169    }