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.Annotations;
021 import org.jetbrains.jet.lang.descriptors.impl.*;
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
055 public ScriptDescriptorImpl(
056 @NotNull DeclarationDescriptor containingDeclaration,
057 int priority,
058 @NotNull JetScope scriptScope,
059 @NotNull Name className
060 ) {
061 super(containingDeclaration, Annotations.EMPTY, NAME);
062 this.priority = priority;
063
064 classDescriptor = new MutableClassDescriptor(containingDeclaration, scriptScope, ClassKind.CLASS, false, className);
065 classDescriptor.addSupertype(KotlinBuiltIns.getInstance().getAnyType());
066 classDescriptor.setModality(Modality.FINAL);
067 classDescriptor.setVisibility(Visibilities.PUBLIC);
068 classDescriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
069
070 classScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.DO_NOTHING, "script members");
071 classScope.changeLockLevel(WritableScope.LockLevel.BOTH);
072 classDescriptor.setScopeForMemberLookup(classScope);
073 classDescriptor.createTypeConstructor();
074 }
075
076 public void initialize(
077 @NotNull JetType returnType,
078 @NotNull List<? extends PropertyDescriptorImpl> properties,
079 @NotNull List<? extends FunctionDescriptor> functions
080 ) {
081 assert valueParameters != null : "setValueParameters() must be called before this method";
082 scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType);
083
084 classScope.addPropertyDescriptor(createScriptResultProperty(this));
085
086 for (PropertyDescriptorImpl property : properties) {
087 classScope.addPropertyDescriptor(property);
088 }
089
090 for (FunctionDescriptor function : functions) {
091 classScope.addFunctionDescriptor(function);
092 }
093 }
094
095 @NotNull
096 public static PropertyDescriptor createScriptResultProperty(@NotNull ScriptDescriptor scriptDescriptor) {
097 PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(scriptDescriptor.getClassDescriptor(),
098 Annotations.EMPTY,
099 Modality.FINAL,
100 Visibilities.PUBLIC,
101 false,
102 Name.identifier(LAST_EXPRESSION_VALUE_FIELD_NAME),
103 CallableMemberDescriptor.Kind.DECLARATION);
104 JetType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType();
105 assert returnType != null : "Return type not initialized for " + scriptDescriptor;
106 propertyDescriptor.setType(
107 returnType,
108 Collections.<TypeParameterDescriptor>emptyList(),
109 scriptDescriptor.getThisAsReceiverParameter(),
110 ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER);
111 propertyDescriptor.initialize(null, null);
112 return propertyDescriptor;
113 }
114
115 @Override
116 public int getPriority() {
117 return priority;
118 }
119
120 @Override
121 @NotNull
122 public ScriptCodeDescriptor getScriptCodeDescriptor() {
123 return scriptCodeDescriptor;
124 }
125
126 @Override
127 @NotNull
128 public ReceiverParameterDescriptor getThisAsReceiverParameter() {
129 return implicitReceiver;
130 }
131
132 @Override
133 public DeclarationDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
134 throw new IllegalStateException("nothing to substitute in script");
135 }
136
137 @Override
138 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
139 return visitor.visitScriptDescriptor(this, data);
140 }
141
142 public void setValueParameters(@NotNull List<ValueParameterDescriptor> valueParameters) {
143 this.valueParameters = valueParameters;
144
145 ConstructorDescriptorImpl constructorDescriptor = createConstructor(this, valueParameters);
146 constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
147 classDescriptor.getConstructors().add(constructorDescriptor);
148 classDescriptor.setPrimaryConstructor(constructorDescriptor);
149
150 for (ValueParameterDescriptor valueParameter : valueParameters) {
151 classScope.addPropertyDescriptor(createPropertyFromScriptParameter(this, valueParameter));
152 }
153 }
154
155 @NotNull
156 public static ConstructorDescriptorImpl createConstructor(
157 @NotNull ScriptDescriptor scriptDescriptor, @NotNull List<ValueParameterDescriptor> valueParameters
158 ) {
159 return ConstructorDescriptorImpl.create(scriptDescriptor.getClassDescriptor(), Annotations.EMPTY, true)
160 .initialize(
161 Collections.<TypeParameterDescriptor>emptyList(),
162 valueParameters,
163 Visibilities.PUBLIC,
164 false
165 );
166 }
167
168 @NotNull
169 public static PropertyDescriptor createPropertyFromScriptParameter(
170 @NotNull ScriptDescriptor scriptDescriptor,
171 @NotNull ValueParameterDescriptor parameter
172 ) {
173 PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(scriptDescriptor.getClassDescriptor(),
174 Annotations.EMPTY,
175 Modality.FINAL,
176 Visibilities.PUBLIC,
177 false,
178 parameter.getName(),
179 CallableMemberDescriptor.Kind.DECLARATION);
180 propertyDescriptor.setType(
181 parameter.getType(),
182 Collections.<TypeParameterDescriptor>emptyList(),
183 scriptDescriptor.getThisAsReceiverParameter(), ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER);
184 propertyDescriptor.initialize(null, null);
185 return propertyDescriptor;
186 }
187
188 @Override
189 @NotNull
190 public ClassDescriptor getClassDescriptor() {
191 return classDescriptor;
192 }
193
194 @Override
195 @NotNull
196 public WritableScope getScopeForBodyResolution() {
197 return scopeForBodyResolution;
198 }
199
200 public void setScopeForBodyResolution(@NotNull WritableScope scopeForBodyResolution) {
201 assert this.scopeForBodyResolution == null : "Scope for body resolution already set for " + this;
202 this.scopeForBodyResolution = scopeForBodyResolution;
203 }
204 }