001    /*
002     * Copyright 2010-2015 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.load.java.descriptors;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.descriptors.*;
022    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
023    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
024    import org.jetbrains.kotlin.name.Name;
025    import org.jetbrains.kotlin.types.JetType;
026    import org.jetbrains.kotlin.types.TypeSubstitutor;
027    
028    import java.util.List;
029    
030    public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implements JavaCallableMemberDescriptor {
031        private enum ParameterNamesStatus {
032            NON_STABLE_DECLARED(false, false),
033            STABLE_DECLARED(true, false),
034            NON_STABLE_SYNTHESIZED(false, true),
035            STABLE_SYNTHESIZED(true, true), // TODO: this makes no sense
036            ;
037    
038            public final boolean isStable;
039            public final boolean isSynthesized;
040    
041            ParameterNamesStatus(boolean isStable, boolean isSynthesized) {
042                this.isStable = isStable;
043                this.isSynthesized = isSynthesized;
044            }
045    
046            @NotNull
047            public static ParameterNamesStatus get(boolean stable, boolean synthesized) {
048                return stable ? (synthesized ? STABLE_SYNTHESIZED : STABLE_DECLARED) :
049                       (synthesized ? NON_STABLE_SYNTHESIZED : NON_STABLE_DECLARED);
050            }
051        }
052    
053        private ParameterNamesStatus parameterNamesStatus = null;
054    
055        protected JavaMethodDescriptor(
056                @NotNull DeclarationDescriptor containingDeclaration,
057                @Nullable SimpleFunctionDescriptor original,
058                @NotNull Annotations annotations,
059                @NotNull Name name,
060                @NotNull Kind kind,
061                @NotNull SourceElement source
062        ) {
063            super(containingDeclaration, original, annotations, name, kind, source);
064        }
065    
066        @NotNull
067        public static JavaMethodDescriptor createJavaMethod(
068                @NotNull DeclarationDescriptor containingDeclaration,
069                @NotNull Annotations annotations,
070                @NotNull Name name,
071                @NotNull SourceElement source
072        ) {
073            return new JavaMethodDescriptor(containingDeclaration, null, annotations, name, Kind.DECLARATION, source);
074        }
075    
076        @Override
077        public boolean hasStableParameterNames() {
078            assert parameterNamesStatus != null : "Parameter names status was not set: " + this;
079            return parameterNamesStatus.isStable;
080        }
081    
082        @Override
083        public boolean hasSynthesizedParameterNames() {
084            assert parameterNamesStatus != null : "Parameter names status was not set: " + this;
085            return parameterNamesStatus.isSynthesized;
086        }
087    
088        public void setParameterNamesStatus(boolean hasStableParameterNames, boolean hasSynthesizedParameterNames) {
089            this.parameterNamesStatus = ParameterNamesStatus.get(hasStableParameterNames, hasSynthesizedParameterNames);
090        }
091    
092        @NotNull
093        @Override
094        protected JavaMethodDescriptor createSubstitutedCopy(
095                @NotNull DeclarationDescriptor newOwner,
096                @Nullable FunctionDescriptor original,
097                @NotNull Kind kind
098        ) {
099            JavaMethodDescriptor result = new JavaMethodDescriptor(
100                    newOwner,
101                    (SimpleFunctionDescriptor) original,
102                    getAnnotations(),
103                    getName(),
104                    kind,
105                    original != null ? original.getSource() : SourceElement.NO_SOURCE
106            );
107            result.setParameterNamesStatus(hasStableParameterNames(), hasSynthesizedParameterNames());
108            return result;
109        }
110    
111        @Override
112        @NotNull
113        public JavaMethodDescriptor enhance(
114                @Nullable JetType enhancedReceiverType,
115                @NotNull List<JetType> enhancedValueParametersTypes,
116                @NotNull JetType enhancedReturnType
117        ) {
118            List<ValueParameterDescriptor> enhancedValueParameters =
119                    DescriptorsPackage.createEnhancedValueParameters(enhancedValueParametersTypes, getValueParameters(), this);
120    
121            // We use `doSubstitute` here because it does exactly what we need:
122            // 1. creates full copy of descriptor
123            // 2. copies method's type parameters (with new containing declaration) and properly substitute to them in value parameters, return type and etc.
124            JavaMethodDescriptor enhancedMethod = (JavaMethodDescriptor) doSubstitute(
125                    TypeSubstitutor.EMPTY, getContainingDeclaration(), getModality(), getVisibility(), false, getOriginal(),
126                    /* copyOverrides = */ true, getKind(),
127                    enhancedValueParameters, enhancedReceiverType, enhancedReturnType
128            );
129    
130            assert enhancedMethod != null : "null after substitution while enhancing " + toString();
131            return enhancedMethod;
132        }
133    }