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.impl;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.jet.lang.descriptors.*;
021 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
022 import org.jetbrains.jet.lang.resolve.name.Name;
023 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
024 import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
025 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
026 import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
027 import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
028 import org.jetbrains.jet.lang.types.JetType;
029 import org.jetbrains.jet.lang.types.TypeSubstitutor;
030 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
031
032 import java.util.Collections;
033 import java.util.List;
034
035 // SCRIPT: Script declaration descriptor
036 public class ScriptDescriptorImpl extends DeclarationDescriptorNonRootImpl implements ScriptDescriptor {
037
038 private final int priority;
039
040 private List<ValueParameterDescriptor> valueParameters;
041
042 private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this);
043 private final ReceiverParameterDescriptor implicitReceiver = new ReceiverParameterDescriptorImpl(this,
044 // Putting Any here makes no sense,
045 // it is simply copied from someplace else
046 // during a refactoring
047 KotlinBuiltIns.getInstance().getAnyType(),
048 new ScriptReceiver(this));
049
050 private final MutableClassDescriptor classDescriptor;
051
052 private final WritableScopeImpl classScope;
053 private WritableScope scopeForBodyResolution;
054 private PropertyDescriptor scriptResultProperty;
055
056 public ScriptDescriptorImpl(
057 @NotNull DeclarationDescriptor containingDeclaration,
058 int priority,
059 @NotNull JetScope scriptScope,
060 @NotNull Name className,
061 @NotNull SourceElement source
062 ) {
063 super(containingDeclaration, Annotations.EMPTY, NAME, source);
064 this.priority = priority;
065
066 classDescriptor = new MutableClassDescriptor(containingDeclaration, scriptScope, ClassKind.CLASS,
067 false, className, SourceElement.NO_SOURCE);
068 classDescriptor.addSupertype(KotlinBuiltIns.getInstance().getAnyType());
069 classDescriptor.setModality(Modality.FINAL);
070 classDescriptor.setVisibility(Visibilities.PUBLIC);
071 classDescriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
072
073 classScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.DO_NOTHING, "script members");
074 classScope.changeLockLevel(WritableScope.LockLevel.BOTH);
075 classDescriptor.setScopeForMemberLookup(classScope);
076 classDescriptor.createTypeConstructor();
077 }
078
079 public void initialize(
080 @NotNull JetType returnType,
081 @NotNull List<? extends PropertyDescriptorImpl> properties,
082 @NotNull List<? extends FunctionDescriptor> functions
083 ) {
084 assert valueParameters != null : "setValueParameters() must be called before this method";
085 scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType);
086
087 scriptResultProperty = createScriptResultProperty(this);
088 classScope.addPropertyDescriptor(scriptResultProperty);
089
090 for (PropertyDescriptorImpl property : properties) {
091 classScope.addPropertyDescriptor(property);
092 }
093
094 for (FunctionDescriptor function : functions) {
095 classScope.addFunctionDescriptor(function);
096 }
097 }
098
099 @NotNull
100 public static PropertyDescriptor createScriptResultProperty(@NotNull ScriptDescriptor scriptDescriptor) {
101 PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(scriptDescriptor.getClassDescriptor(),
102 Annotations.EMPTY,
103 Modality.FINAL,
104 Visibilities.PUBLIC,
105 false,
106 Name.identifier(LAST_EXPRESSION_VALUE_FIELD_NAME),
107 CallableMemberDescriptor.Kind.DECLARATION,
108 SourceElement.NO_SOURCE);
109 JetType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType();
110 assert returnType != null : "Return type not initialized for " + scriptDescriptor;
111 propertyDescriptor.setType(
112 returnType,
113 Collections.<TypeParameterDescriptor>emptyList(),
114 scriptDescriptor.getThisAsReceiverParameter(),
115 ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER);
116 propertyDescriptor.initialize(null, null);
117 return propertyDescriptor;
118 }
119
120 @NotNull
121 @Override
122 public PropertyDescriptor getScriptResultProperty() {
123 return scriptResultProperty;
124 }
125
126 @Override
127 public int getPriority() {
128 return priority;
129 }
130
131 @Override
132 @NotNull
133 public ScriptCodeDescriptor getScriptCodeDescriptor() {
134 return scriptCodeDescriptor;
135 }
136
137 @Override
138 @NotNull
139 public ReceiverParameterDescriptor getThisAsReceiverParameter() {
140 return implicitReceiver;
141 }
142
143 @Override
144 public DeclarationDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
145 throw new IllegalStateException("nothing to substitute in script");
146 }
147
148 @Override
149 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
150 return visitor.visitScriptDescriptor(this, data);
151 }
152
153 public void setValueParameters(@NotNull List<ValueParameterDescriptor> valueParameters) {
154 this.valueParameters = valueParameters;
155
156 ConstructorDescriptorImpl constructorDescriptor = createConstructor(this, valueParameters);
157 constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
158 classDescriptor.getConstructors().add(constructorDescriptor);
159 classDescriptor.setPrimaryConstructor(constructorDescriptor);
160
161 for (ValueParameterDescriptor valueParameter : valueParameters) {
162 classScope.addPropertyDescriptor(createPropertyFromScriptParameter(this, valueParameter));
163 }
164 }
165
166 @NotNull
167 public static ConstructorDescriptorImpl createConstructor(
168 @NotNull ScriptDescriptor scriptDescriptor, @NotNull List<ValueParameterDescriptor> valueParameters
169 ) {
170 return ConstructorDescriptorImpl.create(scriptDescriptor.getClassDescriptor(), Annotations.EMPTY, true, SourceElement.NO_SOURCE)
171 .initialize(
172 Collections.<TypeParameterDescriptor>emptyList(),
173 valueParameters,
174 Visibilities.PUBLIC,
175 false
176 );
177 }
178
179 @NotNull
180 public static PropertyDescriptor createPropertyFromScriptParameter(
181 @NotNull ScriptDescriptor scriptDescriptor,
182 @NotNull ValueParameterDescriptor parameter
183 ) {
184 PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
185 scriptDescriptor.getClassDescriptor(),
186 Annotations.EMPTY,
187 Modality.FINAL,
188 Visibilities.PUBLIC,
189 false,
190 parameter.getName(),
191 CallableMemberDescriptor.Kind.DECLARATION,
192 SourceElement.NO_SOURCE
193 );
194 propertyDescriptor.setType(
195 parameter.getType(),
196 Collections.<TypeParameterDescriptor>emptyList(),
197 scriptDescriptor.getThisAsReceiverParameter(), ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER);
198 propertyDescriptor.initialize(null, null);
199 return propertyDescriptor;
200 }
201
202 @Override
203 @NotNull
204 public ClassDescriptor getClassDescriptor() {
205 return classDescriptor;
206 }
207
208 @Override
209 @NotNull
210 public WritableScope getScopeForBodyResolution() {
211 return scopeForBodyResolution;
212 }
213
214 public void setScopeForBodyResolution(@NotNull WritableScope scopeForBodyResolution) {
215 assert this.scopeForBodyResolution == null : "Scope for body resolution already set for " + this;
216 this.scopeForBodyResolution = scopeForBodyResolution;
217 }
218 }