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