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;
018    
019    import com.intellij.lang.Language;
020    import com.intellij.openapi.util.TextRange;
021    import com.intellij.psi.*;
022    import com.intellij.psi.search.GlobalSearchScope;
023    import com.intellij.psi.search.SearchScope;
024    import com.intellij.util.ArrayUtil;
025    import com.intellij.util.IncorrectOperationException;
026    import org.jetbrains.annotations.NonNls;
027    import org.jetbrains.annotations.NotNull;
028    import org.jetbrains.annotations.Nullable;
029    import org.jetbrains.kotlin.idea.KotlinLanguage;
030    import org.jetbrains.kotlin.psi.*;
031    import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
032    
033    import java.util.List;
034    
035    public class KtLightParameter extends LightParameter implements KtLightDeclaration<KtParameter, PsiParameter> {
036        private static String getName(PsiParameter delegate, int index) {
037            String name = delegate.getName();
038            return name != null ? name : "p" + index;
039        }
040    
041        private final PsiModifierList modifierList;
042        private final PsiParameter delegate;
043        private final int index;
044        private final KtLightMethod method;
045        private KtLightIdentifier lightIdentifier = null;
046    
047        public KtLightParameter(final PsiParameter delegate, int index, KtLightMethod method) {
048            super(getName(delegate, index), delegate.getType(), method, KotlinLanguage.INSTANCE);
049    
050            this.delegate = delegate;
051            this.index = index;
052            this.method = method;
053    
054            if (method.getLightMethodOrigin() instanceof LightMemberOriginForDeclaration) {
055                this.modifierList = new KtLightModifierListWithExplicitModifiers(this, ArrayUtil.EMPTY_STRING_ARRAY) {
056                    @Override
057                    public PsiAnnotationOwner getDelegate() {
058                        return delegate.getModifierList();
059                    }
060                };
061            }
062            else {
063                this.modifierList = super.getModifierList();
064            }
065        }
066    
067        @NotNull
068        @Override
069        public PsiModifierList getModifierList() {
070            return modifierList;
071        }
072    
073        @NotNull
074        @Override
075        public PsiParameter getClsDelegate() {
076            return delegate;
077        }
078    
079        @Nullable
080        @Override
081        public KtParameter getKotlinOrigin() {
082            KtDeclaration declaration = method.getKotlinOrigin();
083            if (declaration == null) return null;
084    
085            int jetIndex = KtPsiUtilKt.isExtensionDeclaration(declaration) ? index - 1 : index;
086            if (jetIndex < 0) return null;
087    
088            if (declaration instanceof KtFunction) {
089                List<KtParameter> paramList = ((KtFunction) declaration).getValueParameters();
090                return jetIndex < paramList.size() ? paramList.get(jetIndex) : null;
091            }
092    
093            if (jetIndex != 0) return null;
094    
095            KtPropertyAccessor setter = null;
096            if (declaration instanceof KtPropertyAccessor) {
097                KtPropertyAccessor accessor = (KtPropertyAccessor) declaration;
098                setter = accessor.isSetter() ? accessor : null;
099            }
100            else if (declaration instanceof KtProperty) {
101                setter = ((KtProperty) declaration).getSetter();
102            }
103    
104            return setter != null ? setter.getParameter() : null;
105        }
106    
107        @NotNull
108        @Override
109        public PsiElement getNavigationElement() {
110            KtParameter origin = getKotlinOrigin();
111            return origin != null ? origin : super.getNavigationElement();
112        }
113    
114        @Override
115        public boolean isValid() {
116            return method.isValid();
117        }
118    
119        @Override
120        public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
121            KtParameter origin = getKotlinOrigin();
122            if (origin != null) {
123                origin.setName(name);
124            }
125            return this;
126        }
127    
128        @Override
129        public PsiFile getContainingFile() {
130            return method.getContainingFile();
131        }
132    
133        @NotNull
134        @Override
135        public Language getLanguage() {
136            return KotlinLanguage.INSTANCE;
137        }
138    
139        @NotNull
140        @Override
141        public SearchScope getUseScope() {
142            KtParameter origin = getKotlinOrigin();
143            return origin != null ? origin.getUseScope() : GlobalSearchScope.EMPTY_SCOPE;
144        }
145    
146        public KtLightMethod getMethod() {
147            return method;
148        }
149    
150        @Override
151        public String getText() {
152            return "";
153        }
154    
155        @Override
156        public TextRange getTextRange() {
157            KtParameter origin = getKotlinOrigin();
158            return origin != null ? origin.getTextRange() : TextRange.EMPTY_RANGE;
159        }
160    
161        @Override
162        public PsiIdentifier getNameIdentifier() {
163            if (lightIdentifier == null) {
164                lightIdentifier = new KtLightIdentifier(this, getKotlinOrigin());
165            }
166            return lightIdentifier;
167        }
168    
169        @Override
170        public PsiElement getParent() {
171            return getMethod().getParameterList();
172        }
173    
174        @Override
175        public boolean isEquivalentTo(PsiElement another) {
176            KtParameter kotlinOrigin = getKotlinOrigin();
177            if (another instanceof KtLightParameter && kotlinOrigin != null) {
178                KtLightParameter anotherParam = (KtLightParameter) another;
179                return kotlinOrigin.equals(anotherParam.getKotlinOrigin()) && getClsDelegate().equals(anotherParam.getClsDelegate());
180            }
181            return super.isEquivalentTo(another);
182        }
183    }