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