001    /*
002     * Copyright 2010-2014 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.jet.lang.resolve.lazy.descriptors;
018    
019    import kotlin.Function0;
020    import kotlin.Function1;
021    import kotlin.KotlinPackage;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.*;
025    import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
026    import org.jetbrains.jet.lang.descriptors.impl.ScriptDescriptorImpl;
027    import org.jetbrains.jet.lang.resolve.BindingTrace;
028    import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
029    import org.jetbrains.jet.lang.resolve.lazy.data.JetScriptInfo;
030    import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider;
031    import org.jetbrains.jet.lang.resolve.name.Name;
032    import org.jetbrains.jet.storage.NotNullLazyValue;
033    
034    import java.util.Collection;
035    import java.util.Set;
036    
037    // SCRIPT: Members of a script class
038    public class LazyScriptClassMemberScope extends LazyClassMemberScope {
039    
040        private final NotNullLazyValue<PropertyDescriptor> scriptResultProperty;
041    
042        protected LazyScriptClassMemberScope(
043                @NotNull ResolveSession _resolveSession,
044                @NotNull ClassMemberDeclarationProvider _declarationProvider,
045                @NotNull LazyClassDescriptor thisClass,
046                @NotNull BindingTrace trace
047        ) {
048            super(_resolveSession, _declarationProvider, thisClass, trace);
049            this.scriptResultProperty = _resolveSession.getStorageManager().createLazyValue(
050                    new Function0<PropertyDescriptor>() {
051                        @Override
052                        public PropertyDescriptor invoke() {
053                            JetScriptInfo scriptInfo = (JetScriptInfo) declarationProvider.getOwnerInfo();
054    
055                            return ScriptDescriptorImpl.createScriptResultProperty(resolveSession.getScriptDescriptor(scriptInfo.getScript()));
056                        }
057                    }
058            );
059        }
060    
061        @NotNull
062        @Override
063        protected Collection<DeclarationDescriptor> computeExtraDescriptors() {
064            return KotlinPackage.plus(
065                    super.computeExtraDescriptors(),
066                    KotlinPackage.plus(
067                        getProperties(Name.identifier(ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME)),
068                        getPropertiesForScriptParameters()
069                    )
070            );
071        }
072    
073        private Collection<VariableDescriptor> getPropertiesForScriptParameters() {
074            return KotlinPackage.flatMap(
075                    getPrimaryConstructor().getValueParameters(),
076                    new Function1<ValueParameterDescriptor, Iterable<? extends VariableDescriptor>>() {
077                        @Override
078                        public Iterable<? extends VariableDescriptor> invoke(ValueParameterDescriptor descriptor) {
079                            return getProperties(descriptor.getName());
080                        }
081                    }
082            );
083        }
084    
085        @Override
086        protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
087            super.getNonDeclaredProperties(name, result);
088    
089            if (name.asString().equals(ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME)) {
090                result.add(scriptResultProperty.invoke());
091            }
092        }
093    
094        @NotNull
095        public PropertyDescriptor getScriptResultProperty() {
096            return scriptResultProperty.invoke();
097        }
098    
099        @Override
100        protected void createPropertiesFromPrimaryConstructorParameters(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
101            JetScriptInfo scriptInfo = (JetScriptInfo) declarationProvider.getOwnerInfo();
102    
103            // From primary constructor parameters
104            ConstructorDescriptor primaryConstructor = getPrimaryConstructor();
105            if (primaryConstructor == null) return;
106    
107            for (ValueParameterDescriptor valueParameterDescriptor : primaryConstructor.getValueParameters()) {
108                if (!name.equals(valueParameterDescriptor.getName())) continue;
109    
110                result.add(
111                        ScriptDescriptorImpl.createPropertyFromScriptParameter(
112                                   resolveSession.getScriptDescriptor(scriptInfo.getScript()),
113                                   valueParameterDescriptor
114                        )
115                );
116            }
117        }
118    
119        @Override
120        @Nullable
121        protected ConstructorDescriptor resolvePrimaryConstructor() {
122            JetScriptInfo scriptInfo = (JetScriptInfo) declarationProvider.getOwnerInfo();
123            ScriptDescriptor scriptDescriptor = resolveSession.getScriptDescriptor(scriptInfo.getScript());
124            ConstructorDescriptorImpl constructor = ScriptDescriptorImpl.createConstructor(scriptDescriptor,
125                                                                                           scriptDescriptor.getScriptCodeDescriptor()
126                                                                                                   .getValueParameters());
127            setDeferredReturnType(constructor);
128            return constructor;
129        }
130    }