making script classes useful/accessable for the rest of the world

This commit is contained in:
Alex Tkachman
2012-08-01 09:58:01 +03:00
parent 1a918d52bb
commit e134969896
21 changed files with 229 additions and 75 deletions
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.utils.Progress; import org.jetbrains.jet.utils.Progress;
import org.jetbrains.asm4.commons.Method; import org.jetbrains.asm4.commons.Method;
@@ -143,7 +144,7 @@ public class GenerationState {
public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) { public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) {
for (JetFile file : this.files) { for (JetFile file : this.files) {
if (file.isScript()) { if (file.isScript()) {
String name = ScriptCodegen.classNameForScript(file); String name = ScriptNameUtil.classNameForScript(file);
injector.getClosureAnnotator().registerClassNameForScript(file.getScript(), JvmClassName.byInternalName(name)); injector.getClosureAnnotator().registerClassNameForScript(file.getScript(), JvmClassName.byInternalName(name));
} }
} }
@@ -17,18 +17,15 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
import org.jetbrains.jet.lang.resolve.java.JdkNames; import org.jetbrains.jet.lang.resolve.java.JdkNames;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.MethodVisitor;
@@ -37,7 +34,6 @@ import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import javax.inject.Inject; import javax.inject.Inject;
import java.io.File;
import java.util.List; import java.util.List;
/** /**
@@ -45,10 +41,6 @@ import java.util.List;
*/ */
public class ScriptCodegen { public class ScriptCodegen {
public static final JvmClassName SCRIPT_DEFAULT_CLASS_NAME = JvmClassName.byInternalName("Script");
public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
@NotNull @NotNull
private GenerationState state; private GenerationState state;
@NotNull @NotNull
@@ -99,7 +91,7 @@ public class ScriptCodegen {
public void generate(JetScript scriptDeclaration) { public void generate(JetScript scriptDeclaration) {
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration); ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration);
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor); ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor);
@@ -134,7 +126,7 @@ public class ScriptCodegen {
Type blockType = jetTypeMapper.mapType(scriptDescriptor.getReturnType(), MapTypeMode.VALUE); Type blockType = jetTypeMapper.mapType(scriptDescriptor.getReturnType(), MapTypeMode.VALUE);
classBuilder.newField(null, Opcodes.ACC_PUBLIC, LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor(), null, null); classBuilder.newField(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_FINAL, ScriptNameUtil.LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor(), null, null);
JvmMethodSignature jvmSignature = jetTypeMapper.mapScriptSignature(scriptDescriptor, importedScripts); JvmMethodSignature jvmSignature = jetTypeMapper.mapScriptSignature(scriptDescriptor, importedScripts);
@@ -196,7 +188,7 @@ public class ScriptCodegen {
StackValue stackValue = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression()); StackValue stackValue = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression());
if (stackValue.type != Type.VOID_TYPE) { if (stackValue.type != Type.VOID_TYPE) {
stackValue.put(stackValue.type, instructionAdapter); stackValue.put(stackValue.type, instructionAdapter);
instructionAdapter.putfield(className.getInternalName(), LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor()); instructionAdapter.putfield(className.getInternalName(), ScriptNameUtil.LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor());
} }
instructionAdapter.areturn(Type.VOID_TYPE); instructionAdapter.areturn(Type.VOID_TYPE);
@@ -213,7 +205,7 @@ public class ScriptCodegen {
for (ValueParameterDescriptor parameter : script.getValueParameters()) { for (ValueParameterDescriptor parameter : script.getValueParameters()) {
Type parameterType = jetTypeMapper.mapType(parameter.getType(), MapTypeMode.VALUE); Type parameterType = jetTypeMapper.mapType(parameter.getType(), MapTypeMode.VALUE);
int access = Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL; int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL;
classBuilder.newField(null, access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null); classBuilder.newField(null, access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null);
} }
} }
@@ -252,26 +244,4 @@ public class ScriptCodegen {
public String getScriptFieldName(@NotNull ScriptDescriptor scriptDescriptor) { public String getScriptFieldName(@NotNull ScriptDescriptor scriptDescriptor) {
return "script$" + getScriptIndex(scriptDescriptor); return "script$" + getScriptIndex(scriptDescriptor);
} }
public static String classNameForScript(JetFile file) {
JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file);
String name = file.getName();
int index = name.lastIndexOf('/');
if(index != -1)
name = name.substring(index+1);
if(name.endsWith(scriptDefinition.getExtension()))
name = name.substring(0, name.length()-scriptDefinition.getExtension().length());
else {
index = name.indexOf('.');
if(index != -1)
name = name.substring(0,index);
}
name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
JetNamespaceHeader header = file.getNamespaceHeader();
if(header != null && header.getName().length() > 0) {
name = header.getName().replace('.','/') + "/" + name;
}
return name;
}
} }
@@ -44,6 +44,7 @@ import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.plugin.JetMainDetector; import org.jetbrains.jet.plugin.JetMainDetector;
@@ -254,7 +255,7 @@ public class KotlinToJVMBytecodeCompiler {
}, },
parentLoader == null ? AllModules.class.getClassLoader() : parentLoader)); parentLoader == null ? AllModules.class.getClassLoader() : parentLoader));
JetFile scriptFile = environment.getSourceFiles().get(0); JetFile scriptFile = environment.getSourceFiles().get(0);
return classLoader.loadClass(ScriptCodegen.classNameForScript(scriptFile)); return classLoader.loadClass(ScriptNameUtil.classNameForScript(scriptFile));
} }
catch (Exception e) { catch (Exception e) {
throw new RuntimeException("Failed to evaluate script: " + e, e); throw new RuntimeException("Failed to evaluate script: " + e, e);
@@ -19,13 +19,28 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
/** /**
@@ -42,14 +57,75 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl {
private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this); private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this);
private final ReceiverDescriptor implicitReceiver = new ScriptReceiver(this); private final ReceiverDescriptor implicitReceiver = new ScriptReceiver(this);
public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration, int priority) { private ClassDescriptorImpl classDescriptor;
private WritableScopeImpl classScope;
private ClassDescriptorImpl descriptor;
private ClassReceiver classReceiver;
public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration, int priority, JetScript script, JetScope scriptScope) {
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), NAME); super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), NAME);
this.priority = priority; this.priority = priority;
String className = ScriptNameUtil.classNameForScript((JetFile) script.getContainingFile()).replace('/','.');
classDescriptor = new ClassDescriptorImpl(
containingDeclaration,
Collections.<AnnotationDescriptor>emptyList(),
Modality.FINAL,
new FqName(className).shortName());
classScope = new WritableScopeImpl(scriptScope, containingDeclaration, RedeclarationHandler.DO_NOTHING, "script members");
classScope.changeLockLevel(WritableScope.LockLevel.BOTH);
classDescriptor.initialize(
false,
Collections.<TypeParameterDescriptor>emptyList(),
Collections.singletonList(JetStandardClasses.getAnyType()),
classScope,
new HashSet<ConstructorDescriptor>(),
null);
classReceiver = new ClassReceiver(classDescriptor);
} }
public void initialize(@NotNull JetType returnType) { public void initialize(@NotNull JetType returnType, JetScript declaration, BindingContext bindingContext) {
this.returnType = returnType; this.returnType = returnType;
scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType); scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor,
Collections.<AnnotationDescriptor>emptyList(),
Modality.FINAL,
Visibilities.PUBLIC,
false,
false,
Name.identifier(ScriptNameUtil.LAST_EXPRESSION_VALUE_FIELD_NAME),
CallableMemberDescriptor.Kind.DECLARATION);
propertyDescriptor.setType(returnType, Collections.<TypeParameterDescriptor>emptyList(), new ClassReceiver(classDescriptor), ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.initialize(null, null);
classScope.addPropertyDescriptor(propertyDescriptor);
for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
if(jetDeclaration instanceof JetProperty) {
VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, jetDeclaration);
assert descriptor != null;
propertyDescriptor = new PropertyDescriptor(classDescriptor,
Collections.<AnnotationDescriptor>emptyList(),
Modality.FINAL,
propertyDescriptor.getVisibility(),
false,
false,
descriptor.getName(),
CallableMemberDescriptor.Kind.DECLARATION);
propertyDescriptor.setType(returnType, Collections.<TypeParameterDescriptor>emptyList(), classReceiver, ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.initialize(null, null);
classScope.addPropertyDescriptor(propertyDescriptor);
}
else if(jetDeclaration instanceof JetNamedFunction) {
SimpleFunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, jetDeclaration);
assert descriptor != null;
SimpleFunctionDescriptor copy =
descriptor.copy(classDescriptor, descriptor.getModality(), false, CallableMemberDescriptor.Kind.DECLARATION, false);
classScope.addFunctionDescriptor(copy);
}
}
} }
public int getPriority() { public int getPriority() {
@@ -88,5 +164,32 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl {
public void setValueParameters(@NotNull List<ValueParameterDescriptor> valueParameters) { public void setValueParameters(@NotNull List<ValueParameterDescriptor> valueParameters) {
this.valueParameters = valueParameters; this.valueParameters = valueParameters;
ConstructorDescriptorImpl constructorDescriptor =
new ConstructorDescriptorImpl(classDescriptor, Collections.<AnnotationDescriptor>emptyList(), true)
.initialize(Collections.<TypeParameterDescriptor>emptyList(), valueParameters, Visibilities.PUBLIC);
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
classDescriptor.getConstructors().add(constructorDescriptor);
classDescriptor.setPrimaryConstructor(constructorDescriptor);
for (ValueParameterDescriptor parameter : valueParameters) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor,
Collections.<AnnotationDescriptor>emptyList(),
Modality.FINAL,
Visibilities.PUBLIC,
false,
false,
parameter.getName(),
CallableMemberDescriptor.Kind.DECLARATION);
propertyDescriptor.setType(parameter.getType(), Collections.<TypeParameterDescriptor>emptyList(), classReceiver, ReceiverDescriptor.NO_RECEIVER);
//PropertyGetterDescriptor getter = DescriptorResolver.createDefaultGetter(propertyDescriptor);
//getter.initialize(propertyDescriptor.getType());
propertyDescriptor.initialize(null, null);
classScope.addPropertyDescriptor(propertyDescriptor);
}
}
public ClassDescriptor getClassDescriptor() {
return classDescriptor;
} }
} }
@@ -108,6 +108,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker fileMarker = mark(); PsiBuilder.Marker fileMarker = mark();
PsiBuilder.Marker namespaceHeader = mark(); PsiBuilder.Marker namespaceHeader = mark();
PsiBuilder.Marker firstEntry = mark();
parseModifierList(MODIFIER_LIST, true); parseModifierList(MODIFIER_LIST, true);
if (at(PACKAGE_KEYWORD)) { if (at(PACKAGE_KEYWORD)) {
@@ -115,12 +116,13 @@ public class JetParsing extends AbstractJetParsing {
parseNamespaceName(); parseNamespaceName();
firstEntry.drop();
consumeIf(SEMICOLON); consumeIf(SEMICOLON);
namespaceHeader.done(NAMESPACE_HEADER);
} }
else { else {
namespaceHeader.rollbackTo(); firstEntry.rollbackTo();
} }
namespaceHeader.done(NAMESPACE_HEADER);
PsiBuilder.Marker scriptMarker = mark(); PsiBuilder.Marker scriptMarker = mark();
parseImportDirectives(); parseImportDirectives();
@@ -875,7 +875,7 @@ public class DescriptorResolver {
return getterDescriptor; return getterDescriptor;
} }
private PropertyGetterDescriptor createDefaultGetter(PropertyDescriptor propertyDescriptor) { public static PropertyGetterDescriptor createDefaultGetter(PropertyDescriptor propertyDescriptor) {
PropertyGetterDescriptor getterDescriptor; PropertyGetterDescriptor getterDescriptor;
getterDescriptor = new PropertyGetterDescriptor( getterDescriptor = new PropertyGetterDescriptor(
propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), propertyDescriptor.getModality(), propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), propertyDescriptor.getModality(),
@@ -81,7 +81,7 @@ public class ScriptBodyResolver {
if (returnType == null) { if (returnType == null) {
returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null"); returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null");
} }
descriptor.initialize(returnType); descriptor.initialize(returnType, declaration, trace.getBindingContext());
} }
} }
@@ -17,41 +17,27 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Key;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition; import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider; import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
import org.jetbrains.jet.lang.psi.JetScript; import org.jetbrains.jet.lang.psi.JetScript;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler; import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.expressions.CoercionStrategy;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.ref.JetTypeName; import org.jetbrains.jet.lang.types.ref.JetTypeName;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
/** /**
* @author Stepan Koltsov * @author Stepan Koltsov
@@ -127,14 +113,17 @@ public class ScriptHeaderResolver {
} }
public void processScriptHierarchy(@NotNull JetScript script, @NotNull JetScope outerScope) { public void processScriptHierarchy(@NotNull JetScript script, @NotNull JetScope outerScope) {
NamespaceDescriptorImpl ns = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT); JetFile file = (JetFile) script.getContainingFile();
JetNamespaceHeader namespaceHeader = file.getNamespaceHeader();
FqName fqName = namespaceHeader != null ? new FqName(namespaceHeader.getQualifiedName()) : FqName.ROOT;
NamespaceDescriptorImpl ns = namespaceFactory.createNamespaceDescriptorPathIfNeeded(fqName);
Integer priority = script.getUserData(PRIORITY_KEY); Integer priority = script.getUserData(PRIORITY_KEY);
if (priority == null) { if (priority == null) {
priority = 0; priority = 0;
} }
ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority); ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority, script, outerScope);
//WriteThroughScope scriptScope = new WriteThroughScope( //WriteThroughScope scriptScope = new WriteThroughScope(
// outerScope, ns.getMemberScope(), new TraceBasedRedeclarationHandler(trace)); // outerScope, ns.getMemberScope(), new TraceBasedRedeclarationHandler(trace));
WritableScopeImpl scriptScope = new WritableScopeImpl(outerScope, scriptDescriptor, RedeclarationHandler.DO_NOTHING, "script"); WritableScopeImpl scriptScope = new WritableScopeImpl(outerScope, scriptDescriptor, RedeclarationHandler.DO_NOTHING, "script");
@@ -142,7 +131,10 @@ public class ScriptHeaderResolver {
context.getScriptScopes().put(script, scriptScope); context.getScriptScopes().put(script, scriptScope);
context.getScripts().put(script, scriptDescriptor); context.getScripts().put(script, scriptDescriptor);
trace.record(BindingContext.SCRIPT, script, scriptDescriptor); trace.record(BindingContext.SCRIPT, script, scriptDescriptor);
((WritableScope)outerScope).addClassifierDescriptor(scriptDescriptor.getClassDescriptor());
} }
public void resolveScriptDeclarations() { public void resolveScriptDeclarations() {
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
/**
* @author alex.tkachman
*/
public class ScriptNameUtil {
public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
private ScriptNameUtil() {
}
public static String classNameForScript(JetFile file) {
JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file);
String name = file.getName();
int index = name.lastIndexOf('/');
if(index != -1)
name = name.substring(index+1);
if(name.endsWith(scriptDefinition.getExtension()))
name = name.substring(0, name.length()-scriptDefinition.getExtension().length());
else {
index = name.indexOf('.');
if(index != -1)
name = name.substring(0,index);
}
name = Character.toUpperCase(name.charAt(0)) + (name.length() == 0 ? "" : name.substring(1));
JetNamespaceHeader header = file.getNamespaceHeader();
if(header != null && header.getName().length() > 0) {
name = header.getName().replace('.','/') + "/" + name;
}
return name;
}
}
@@ -35,10 +35,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** /**
* @author abreslav * @author abreslav
@@ -156,8 +153,10 @@ public class TopDownAnalyzer {
for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) { for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) {
mutableClassDescriptor.lockScopes(); mutableClassDescriptor.lockScopes();
} }
for (WritableScope namespaceScope : context.getNamespaceScopes().values()) { for (Map.Entry<JetFile, WritableScope> namespaceScope : context.getNamespaceScopes().entrySet()) {
namespaceScope.changeLockLevel(WritableScope.LockLevel.READING); // todo: this is hack in favor of REPL
if(!namespaceScope.getKey().isScript())
namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING);
} }
} }
@@ -193,12 +193,6 @@ public class TypeHierarchyResolver {
declaration.accept(new JetVisitorVoid() { declaration.accept(new JetVisitorVoid() {
@Override @Override
public void visitJetFile(JetFile file) { public void visitJetFile(JetFile file) {
if (file.isScript()) {
JetScript script = file.getScript();
scriptHeaderResolver.processScriptHierarchy(script, outerScope);
return;
}
NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded( NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded(
file, outerScope, RedeclarationHandler.DO_NOTHING); file, outerScope, RedeclarationHandler.DO_NOTHING);
context.getNamespaceDescriptors().put(file, namespaceDescriptor); context.getNamespaceDescriptors().put(file, namespaceDescriptor);
@@ -208,6 +202,10 @@ public class TypeHierarchyResolver {
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH); namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getNamespaceScopes().put(file, namespaceScope); context.getNamespaceScopes().put(file, namespaceScope);
if(file.isScript()) {
scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope);
}
prepareForDeferredCall(namespaceScope, namespaceDescriptor, file); prepareForDeferredCall(namespaceScope, namespaceDescriptor, file);
} }
+1 -1
View File
@@ -5,4 +5,4 @@ fun fib(n: Int): Int {
return v return v
} }
val result = fib(num) public val result = fib(num)
@@ -8,3 +8,4 @@ fun fib(n: Int): Int {
} }
val result = fib(num) val result = fib(num)
12
@@ -0,0 +1,4 @@
val fibwp = test.Fibwp(5)
val callResult = fibwp.fib(4)
val result = fibwp.num + fibwp.result - 5
fibwp.rv
@@ -1,4 +1,6 @@
JetFile: ComplexScript.ktscript JetFile: ComplexScript.ktscript
NAMESPACE_HEADER
<empty list>
SCRIPT SCRIPT
BLOCK BLOCK
FUN FUN
+2
View File
@@ -1,4 +1,6 @@
JetFile: Import.ktscript JetFile: Import.ktscript
NAMESPACE_HEADER
<empty list>
SCRIPT SCRIPT
IMPORT_DIRECTIVE IMPORT_DIRECTIVE
PsiElement(import)('import') PsiElement(import)('import')
+2
View File
@@ -1,6 +1,8 @@
JetFile: Shebang.ktscript JetFile: Shebang.ktscript
PsiComment(SHEBANG_COMMENT)('#!/usr/bin/env kotlin') PsiComment(SHEBANG_COMMENT)('#!/usr/bin/env kotlin')
PsiWhiteSpace('\n\n') PsiWhiteSpace('\n\n')
NAMESPACE_HEADER
<empty list>
SCRIPT SCRIPT
BLOCK BLOCK
CALL_EXPRESSION CALL_EXPRESSION
@@ -1,4 +1,6 @@
JetFile: ShebangIncorrect.ktscript JetFile: ShebangIncorrect.ktscript
NAMESPACE_HEADER
<empty list>
SCRIPT SCRIPT
BLOCK BLOCK
CALL_EXPRESSION CALL_EXPRESSION
@@ -1,4 +1,6 @@
JetFile: SimpleScript.ktscript JetFile: SimpleScript.ktscript
NAMESPACE_HEADER
<empty list>
SCRIPT SCRIPT
BLOCK BLOCK
CALL_EXPRESSION CALL_EXPRESSION
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys; import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys;
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode; import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
import org.jetbrains.jet.utils.ExceptionUtils; import org.jetbrains.jet.utils.ExceptionUtils;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
@@ -188,7 +189,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
try { try {
if (myFiles.isScript()) { if (myFiles.isScript()) {
String scriptClassName = ScriptCodegen.classNameForScript(myFiles.getPsiFile()); String scriptClassName = ScriptNameUtil.classNameForScript(myFiles.getPsiFile());
Class<?> scriptClass = loader.loadClass(scriptClassName); Class<?> scriptClass = loader.loadClass(scriptClassName);
Constructor constructor = getConstructor(scriptClass, state.getScriptConstructorMethod()); Constructor constructor = getConstructor(scriptClass, state.getScriptConstructorMethod());
@@ -127,4 +127,22 @@ public class ScriptGenTest extends CodegenTestCase {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public void testDependentScripts() {
JetScriptDefinitionProvider.getInstance(myEnvironment.getProject()).addScriptDefinition(FIB_SCRIPT_DEFINITION);
loadFiles("script/fibwp.lang.kt", "script/fibwprunner.ktscript");
System.out.println(generateToText());
final Class aClass = loadClass("Fibwprunner", generateClassesInFile());
try {
Constructor constructor = aClass.getConstructor();
Field result = aClass.getField("result");
Field rv = aClass.getField("rv");
Object script = constructor.newInstance();
assertEquals(12,rv.get(script));
assertEquals(8,result.get(script));
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
} }