001    /*
002     * Copyright 2010-2013 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.descriptors;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
021    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
022    import org.jetbrains.jet.lang.descriptors.impl.*;
023    import org.jetbrains.jet.lang.resolve.DescriptorFactory;
024    import org.jetbrains.jet.lang.resolve.name.Name;
025    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
026    import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
027    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
028    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
029    import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
030    import org.jetbrains.jet.lang.types.JetType;
031    import org.jetbrains.jet.lang.types.TypeSubstitutor;
032    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
033    
034    import java.util.Collections;
035    import java.util.HashSet;
036    import java.util.List;
037    
038    public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl {
039        public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
040        private static final Name NAME = Name.special("<script>");
041    
042        private final int priority;
043    
044        private JetType returnType;
045        private List<ValueParameterDescriptor> valueParameters;
046    
047        private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this);
048        private final ReceiverParameterDescriptor implicitReceiver = new ReceiverParameterDescriptorImpl(this,
049                                                                                                         // Putting Any here makes no sense,
050                                                                                                         // it is simply copied from someplace else
051                                                                                                         // during a refactoring
052                                                                                                         KotlinBuiltIns.getInstance().getAnyType(),
053                                                                                                         new ScriptReceiver(this));
054    
055        private final ClassDescriptorImpl classDescriptor;
056    
057        private final WritableScopeImpl classScope;
058    
059        public ScriptDescriptor(
060                @NotNull DeclarationDescriptor containingDeclaration,
061                int priority,
062                @NotNull JetScope scriptScope,
063                @NotNull Name className
064        ) {
065            super(containingDeclaration, Annotations.EMPTY, NAME);
066            this.priority = priority;
067    
068            classDescriptor = new ClassDescriptorImpl(containingDeclaration, className, Modality.FINAL,
069                                                      Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()));
070            classScope = new WritableScopeImpl(scriptScope, containingDeclaration, RedeclarationHandler.DO_NOTHING, "script members");
071            classScope.changeLockLevel(WritableScope.LockLevel.BOTH);
072            classDescriptor.initialize(classScope, new HashSet<ConstructorDescriptor>(), null);
073        }
074    
075        public void initialize(
076                @NotNull JetType returnType,
077                @NotNull List<? extends PropertyDescriptorImpl> properties,
078                @NotNull List<? extends FunctionDescriptor> functions
079        ) {
080            this.returnType = returnType;
081            scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType);
082    
083            PropertyDescriptorImpl propertyDescriptor = new PropertyDescriptorImpl(classDescriptor,
084                                                                   Annotations.EMPTY,
085                                                                   Modality.FINAL,
086                                                                   Visibilities.PUBLIC,
087                                                                   false,
088                                                                   Name.identifier(LAST_EXPRESSION_VALUE_FIELD_NAME),
089                                                                   CallableMemberDescriptor.Kind.DECLARATION);
090            propertyDescriptor.setType(
091                    returnType,
092                    Collections.<TypeParameterDescriptor>emptyList(),
093                    classDescriptor.getThisAsReceiverParameter(),
094                    ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER);
095            propertyDescriptor.initialize(null, null);
096            classScope.addPropertyDescriptor(propertyDescriptor);
097    
098            for (PropertyDescriptorImpl property : properties) {
099                initializeWithDefaultGetterSetter(property);
100                classScope.addPropertyDescriptor(property);
101            }
102    
103            for (FunctionDescriptor function : functions) {
104                classScope.addFunctionDescriptor(function);
105            }
106        }
107    
108        public static void initializeWithDefaultGetterSetter(PropertyDescriptorImpl propertyDescriptor) {
109            PropertyGetterDescriptorImpl getter = propertyDescriptor.getGetter();
110            if (getter == null && propertyDescriptor.getVisibility() != Visibilities.PRIVATE) {
111                getter = DescriptorFactory.createDefaultGetter(propertyDescriptor);
112                getter.initialize(propertyDescriptor.getType());
113            }
114    
115            PropertySetterDescriptor setter = propertyDescriptor.getSetter();
116            if (setter == null && propertyDescriptor.isVar()) {
117                setter = DescriptorFactory.createDefaultSetter(propertyDescriptor);
118            }
119            propertyDescriptor.initialize(getter, setter);
120        }
121    
122        public int getPriority() {
123            return priority;
124        }
125    
126        @NotNull
127        public JetType getReturnType() {
128            return returnType;
129        }
130    
131        @NotNull
132        public List<ValueParameterDescriptor> getValueParameters() {
133            return valueParameters;
134        }
135    
136        @NotNull
137        public ScriptCodeDescriptor getScriptCodeDescriptor() {
138            return scriptCodeDescriptor;
139        }
140    
141        @NotNull
142        public ReceiverParameterDescriptor getThisAsReceiverParameter() {
143            return implicitReceiver;
144        }
145    
146        @Override
147        public DeclarationDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
148            throw new IllegalStateException("nothing to substitute in script");
149        }
150    
151        @Override
152        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
153            return visitor.visitScriptDescriptor(this, data);
154        }
155    
156        public void setValueParameters(@NotNull List<ValueParameterDescriptor> valueParameters) {
157            this.valueParameters = valueParameters;
158            ConstructorDescriptorImpl constructorDescriptor =
159                    new ConstructorDescriptorImpl(classDescriptor, Annotations.EMPTY, true)
160                            .initialize(Collections.<TypeParameterDescriptor>emptyList(), valueParameters, Visibilities.PUBLIC);
161            constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
162    
163            classDescriptor.getConstructors().add(constructorDescriptor);
164            classDescriptor.setPrimaryConstructor(constructorDescriptor);
165    
166            for (ValueParameterDescriptor parameter : valueParameters) {
167                PropertyDescriptorImpl propertyDescriptor = new PropertyDescriptorImpl(classDescriptor,
168                                                                       Annotations.EMPTY,
169                                                                       Modality.FINAL,
170                                                                       Visibilities.PUBLIC,
171                                                                       false,
172                                                                       parameter.getName(),
173                                                                       CallableMemberDescriptor.Kind.DECLARATION);
174                propertyDescriptor.setType(
175                        parameter.getType(),
176                        Collections.<TypeParameterDescriptor>emptyList(),
177                        classDescriptor.getThisAsReceiverParameter(), ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER);
178                //PropertyGetterDescriptor getter = DescriptorResolver.createDefaultGetter(propertyDescriptor);
179                //getter.initialize(propertyDescriptor.getType());
180                propertyDescriptor.initialize(null, null);
181                classScope.addPropertyDescriptor(propertyDescriptor);
182            }
183        }
184    
185        @NotNull
186        public ClassDescriptor getClassDescriptor() {
187            return classDescriptor;
188        }
189    }