Merge branch 'master' of ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
<target name="jarRT" depends="compileRT">
|
||||
<jar destfile="${output}/kotlin-runtime.jar">
|
||||
<fileset dir="${output}/classes/runtime"/>
|
||||
<fileset dir="${basedir}/stdlib/ktSrc"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
this.intrinsics = state.getIntrinsics();
|
||||
}
|
||||
|
||||
private CallableMethod asCallableMethod(FunctionDescriptor fd) {
|
||||
private static CallableMethod asCallableMethod(FunctionDescriptor fd) {
|
||||
Method descriptor = ClosureCodegen.erasedInvokeSignature(fd);
|
||||
String owner = ClosureCodegen.getInternalClassName(fd);
|
||||
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
|
||||
@@ -1187,7 +1187,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
mask |= (1 << index);
|
||||
}
|
||||
else if(resolvedValueArgument instanceof VarargValueArgument) {
|
||||
throw new UnsupportedOperationException("Varargs are not supported yet");
|
||||
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
|
||||
JetType outType = valueParameterDescriptor.getOutType();
|
||||
|
||||
Type type = typeMapper.mapType(outType);
|
||||
assert type.getSort() == Type.ARRAY;
|
||||
Type elementType = type.getElementType();
|
||||
int size = valueArgument.getArgumentExpressions().size();
|
||||
|
||||
v.iconst(valueArgument.getArgumentExpressions().size());
|
||||
v.newarray(elementType);
|
||||
for(int i = 0; i != size; ++i) {
|
||||
v.dup();
|
||||
v.iconst(i);
|
||||
gen(valueArgument.getArgumentExpressions().get(i), elementType);
|
||||
StackValue.arrayElement(elementType, false).store(v);
|
||||
}
|
||||
|
||||
// throw new UnsupportedOperationException("Varargs are not supported yet");
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
@@ -1238,29 +1255,44 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
public StackValue visitSafeQualifiedExpression(JetSafeQualifiedExpression expression, StackValue receiver) {
|
||||
genToJVMStack(expression.getReceiverExpression());
|
||||
Label ifnull = new Label();
|
||||
Label end = new Label();
|
||||
v.dup();
|
||||
v.ifnull(ifnull);
|
||||
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getReceiverExpression());
|
||||
StackValue propValue = genQualified(StackValue.onStack(typeMapper.mapType(receiverType)), expression.getSelectorExpression());
|
||||
Type type = propValue.type;
|
||||
propValue.put(type, v);
|
||||
if(JetTypeMapper.isPrimitive(type) && !type.equals(Type.VOID_TYPE)) {
|
||||
StackValue.valueOf(v, type);
|
||||
type = JetTypeMapper.boxType(type);
|
||||
}
|
||||
v.goTo(end);
|
||||
JetExpression expr = expression.getReceiverExpression();
|
||||
JetType receiverJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getReceiverExpression());
|
||||
Type receiverType = typeMapper.mapType(receiverJetType);
|
||||
gen(expr, receiverType);
|
||||
if(receiverType.getSort() != Type.OBJECT && receiverType.getSort() != Type.ARRAY) {
|
||||
StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression());
|
||||
Type type = propValue.type;
|
||||
propValue.put(type, v);
|
||||
if(JetTypeMapper.isPrimitive(type) && !type.equals(Type.VOID_TYPE)) {
|
||||
StackValue.valueOf(v, type);
|
||||
type = JetTypeMapper.boxType(type);
|
||||
}
|
||||
|
||||
v.mark(ifnull);
|
||||
v.pop();
|
||||
if(!propValue.type.equals(Type.VOID_TYPE)) {
|
||||
v.aconst(null);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
v.mark(end);
|
||||
else {
|
||||
Label ifnull = new Label();
|
||||
Label end = new Label();
|
||||
v.dup();
|
||||
v.ifnull(ifnull);
|
||||
StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression());
|
||||
Type type = propValue.type;
|
||||
propValue.put(type, v);
|
||||
if(JetTypeMapper.isPrimitive(type) && !type.equals(Type.VOID_TYPE)) {
|
||||
StackValue.valueOf(v, type);
|
||||
type = JetTypeMapper.boxType(type);
|
||||
}
|
||||
v.goTo(end);
|
||||
|
||||
return StackValue.onStack(type);
|
||||
v.mark(ifnull);
|
||||
v.pop();
|
||||
if(!propValue.type.equals(Type.VOID_TYPE)) {
|
||||
v.aconst(null);
|
||||
}
|
||||
v.mark(end);
|
||||
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class GeneratedClassLoader extends ClassLoader {
|
||||
private final ClassFileFactory state;
|
||||
|
||||
public GeneratedClassLoader(ClassFileFactory state) {
|
||||
super(GeneratedClassLoader.class.getClassLoader());
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String file = name.replace('.', '/') + ".class";
|
||||
if (state.files().contains(file)) {
|
||||
byte[] bytes = state.asBytes(file);
|
||||
return defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
@@ -360,10 +361,6 @@ public class JetTypeMapper {
|
||||
if (jetType.equals(standardLibrary.getNullableBooleanType())) {
|
||||
return JL_BOOLEAN_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getStringType()) || jetType.equals(standardLibrary.getNullableStringType())) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
|
||||
if(jetType.equals(standardLibrary.getByteArrayType())){
|
||||
return ARRAY_BYTE_TYPE;
|
||||
}
|
||||
@@ -389,6 +386,10 @@ public class JetTypeMapper {
|
||||
return ARRAY_BOOL_TYPE;
|
||||
}
|
||||
|
||||
if (jetType.equals(standardLibrary.getStringType()) || jetType.equals(standardLibrary.getNullableStringType())) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (standardLibrary.getArray().equals(descriptor)) {
|
||||
if (jetType.getArguments().size() != 1) {
|
||||
@@ -415,6 +416,34 @@ public class JetTypeMapper {
|
||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||
}
|
||||
|
||||
public static Type unboxType(final Type type) {
|
||||
if (type == JL_INTEGER_TYPE) {
|
||||
return Type.INT_TYPE;
|
||||
}
|
||||
else if (type == JL_BOOLEAN_TYPE) {
|
||||
return Type.BOOLEAN_TYPE;
|
||||
}
|
||||
else if (type == JL_CHAR_TYPE) {
|
||||
return Type.CHAR_TYPE;
|
||||
}
|
||||
else if (type == JL_SHORT_TYPE) {
|
||||
return Type.SHORT_TYPE;
|
||||
}
|
||||
else if (type == JL_LONG_TYPE) {
|
||||
return Type.LONG_TYPE;
|
||||
}
|
||||
else if (type == JL_BYTE_TYPE) {
|
||||
return Type.BYTE_TYPE;
|
||||
}
|
||||
else if (type == JL_FLOAT_TYPE) {
|
||||
return Type.FLOAT_TYPE;
|
||||
}
|
||||
else if (type == JL_DOUBLE_TYPE) {
|
||||
return Type.DOUBLE_TYPE;
|
||||
}
|
||||
throw new UnsupportedOperationException("Unboxing: " + type);
|
||||
}
|
||||
|
||||
public static Type boxType(Type asmType) {
|
||||
switch (asmType.getSort()) {
|
||||
case Type.VOID:
|
||||
@@ -462,9 +491,6 @@ public class JetTypeMapper {
|
||||
}
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
Type type = mapType(parameter.getOutType());
|
||||
if(parameter.isVararg()) {
|
||||
type = Type.getType("[" + type.getDescriptor());
|
||||
}
|
||||
valueParameterTypes.add(type);
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
@@ -488,7 +514,7 @@ public class JetTypeMapper {
|
||||
return mapToCallableMethod(functionDescriptor, kind);
|
||||
}
|
||||
|
||||
CallableMethod mapToCallableMethod(PsiMethod method) {
|
||||
static CallableMethod mapToCallableMethod(PsiMethod method) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
String owner = jvmName(containingClass);
|
||||
Method signature = getMethodDescriptor(method);
|
||||
@@ -562,13 +588,7 @@ public class JetTypeMapper {
|
||||
parameterTypes.add(mapType(receiver.getType()));
|
||||
}
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
if(parameter.isVararg()) {
|
||||
Type type = mapType(parameter.getOutType());
|
||||
type = Type.getType("[" + type.getDescriptor());
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
else
|
||||
parameterTypes.add(mapType(parameter.getOutType()));
|
||||
parameterTypes.add(mapType(parameter.getOutType()));
|
||||
}
|
||||
Type returnType = mapReturnType(f.getReturnType());
|
||||
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
|
||||
@@ -681,6 +681,9 @@ public abstract class StackValue {
|
||||
case Type.INT:
|
||||
return JetTypeMapper.TYPE_SHARED_INT;
|
||||
|
||||
case Type.LONG:
|
||||
return JetTypeMapper.TYPE_SHARED_LONG;
|
||||
|
||||
case Type.BOOLEAN:
|
||||
return JetTypeMapper.TYPE_SHARED_BOOLEAN;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -21,6 +22,10 @@ public class BinaryOp implements IntrinsicMethod {
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if(nullable) {
|
||||
expectedType = JetTypeMapper.unboxType(expectedType);
|
||||
}
|
||||
if (arguments.size() == 1) {
|
||||
// intrinsic is called as an ordinary function
|
||||
if (receiver != null) {
|
||||
@@ -33,6 +38,10 @@ public class BinaryOp implements IntrinsicMethod {
|
||||
codegen.gen(arguments.get(1), expectedType);
|
||||
}
|
||||
v.visitInsn(expectedType.getOpcode(opcode));
|
||||
|
||||
if(nullable) {
|
||||
StackValue.onStack(expectedType).put(expectedType = JetTypeMapper.boxType(expectedType), v);
|
||||
}
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<orderEntry type="module" module-name="backend" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="stdlib" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.jetbrains.jet.cli;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import org.jetbrains.jet.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
|
||||
import org.jetbrains.jet.plugin.JetFileType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class CompileSession {
|
||||
private final JetCoreEnvironment myEnvironment;
|
||||
private final List<JetNamespace> mySourceFileNamespaces = new ArrayList<JetNamespace>();
|
||||
private final List<JetNamespace> myLibrarySourceFileNamespaces = new ArrayList<JetNamespace>();
|
||||
private List<String> myErrors = new ArrayList<String>();
|
||||
private BindingContext myBindingContext;
|
||||
|
||||
public CompileSession(JetCoreEnvironment environment) {
|
||||
myEnvironment = environment;
|
||||
}
|
||||
|
||||
public void addSources(String path) {
|
||||
VirtualFile vFile = myEnvironment.getLocalFileSystem().findFileByPath(path);
|
||||
if (vFile == null) {
|
||||
myErrors.add("File/directory not found: " + path);
|
||||
return;
|
||||
}
|
||||
if (!vFile.isDirectory() && vFile.getFileType() != JetFileType.INSTANCE) {
|
||||
myErrors.add("Not a Kotlin file: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
addSources(vFile);
|
||||
}
|
||||
|
||||
public void addSources(VirtualFile vFile) {
|
||||
if (vFile.isDirectory()) {
|
||||
for (VirtualFile virtualFile : vFile.getChildren()) {
|
||||
if (virtualFile.getFileType() == JetFileType.INSTANCE) {
|
||||
addSources(virtualFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiFile psiFile = PsiManager.getInstance(myEnvironment.getProject()).findFile(vFile);
|
||||
if (psiFile instanceof JetFile) {
|
||||
mySourceFileNamespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addLibrarySources(VirtualFile vFile) {
|
||||
PsiFile psiFile = PsiManager.getInstance(myEnvironment.getProject()).findFile(vFile);
|
||||
if (psiFile instanceof JetFile) {
|
||||
myLibrarySourceFileNamespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
}
|
||||
}
|
||||
|
||||
public List<JetNamespace> getSourceFileNamespaces() {
|
||||
return mySourceFileNamespaces;
|
||||
}
|
||||
|
||||
public boolean analyze() {
|
||||
if (!myErrors.isEmpty()) {
|
||||
for (String error : myErrors) {
|
||||
System.out.println(error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
final AnalyzingUtils instance = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS);
|
||||
List<JetNamespace> allNamespaces = new ArrayList<JetNamespace>(mySourceFileNamespaces);
|
||||
allNamespaces.addAll(myLibrarySourceFileNamespaces);
|
||||
myBindingContext = instance.analyzeNamespaces(myEnvironment.getProject(), allNamespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY);
|
||||
ErrorCollector errorCollector = new ErrorCollector(myBindingContext);
|
||||
errorCollector.report();
|
||||
return !errorCollector.hasErrors;
|
||||
}
|
||||
|
||||
public ClassFileFactory generate() {
|
||||
GenerationState generationState = new GenerationState(myEnvironment.getProject(), false);
|
||||
generationState.compileCorrectNamespaces(myBindingContext, mySourceFileNamespaces);
|
||||
return generationState.getFactory();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.jetbrains.jet.cli;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
|
||||
import org.jetbrains.jet.lang.diagnostics.Severity;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
class ErrorCollector {
|
||||
Multimap<PsiFile,DiagnosticWithTextRange> maps = LinkedHashMultimap.<PsiFile, DiagnosticWithTextRange>create();
|
||||
|
||||
boolean hasErrors;
|
||||
|
||||
public ErrorCollector(BindingContext bindingContext) {
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
report(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
private void report(Diagnostic diagnostic) {
|
||||
hasErrors |= diagnostic.getSeverity() == Severity.ERROR;
|
||||
if(diagnostic instanceof DiagnosticWithTextRange) {
|
||||
DiagnosticWithTextRange diagnosticWithTextRange = (DiagnosticWithTextRange) diagnostic;
|
||||
maps.put(diagnosticWithTextRange.getPsiFile(), diagnosticWithTextRange);
|
||||
}
|
||||
else {
|
||||
System.out.println(diagnostic.getSeverity().toString() + ": " + diagnostic.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void report() {
|
||||
if(!maps.isEmpty()) {
|
||||
for (PsiFile psiFile : maps.keySet()) {
|
||||
System.out.println(psiFile.getVirtualFile().getPath());
|
||||
Collection<DiagnosticWithTextRange> diagnosticWithTextRanges = maps.get(psiFile);
|
||||
for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) {
|
||||
String position = DiagnosticUtils.formatPosition(diagnosticWithTextRange);
|
||||
System.out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +1,45 @@
|
||||
package org.jetbrains.jet.cli;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.intellij.core.JavaCoreEnvironment;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.Processor;
|
||||
import com.sampullara.cli.Args;
|
||||
import com.sampullara.cli.Argument;
|
||||
import jet.modules.IModuleBuilder;
|
||||
import jet.modules.IModuleSetBuilder;
|
||||
import org.jetbrains.jet.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
|
||||
import org.jetbrains.jet.lang.diagnostics.Severity;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.codegen.GeneratedClassLoader;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
|
||||
import org.jetbrains.jet.plugin.JetMainDetector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.jar.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
public class KotlinCompiler {
|
||||
public static class Arguments {
|
||||
@Argument(value = "output", description = "output directory")
|
||||
public String outputDir;
|
||||
@Argument(value = "src", description = "source file or directory", required = true)
|
||||
@Argument(value = "jar", description = "jar file name")
|
||||
public String jar;
|
||||
@Argument(value = "src", description = "source file or directory")
|
||||
public String src;
|
||||
@Argument(value = "module", description = "module to compile")
|
||||
public String module;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -52,7 +49,7 @@ public class KotlinCompiler {
|
||||
Args.parse(arguments, args);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
System.out.println("Usage: KotlinCompiler -output <outputDir> -src <filename or dirname>");
|
||||
System.out.println("Usage: KotlinCompiler [-output <outputDir>|-jar <jarFileName>] -src <filename or dirname>");
|
||||
t.printStackTrace();
|
||||
return;
|
||||
}
|
||||
@@ -68,107 +65,238 @@ public class KotlinCompiler {
|
||||
if (rtJar == null) return;
|
||||
|
||||
environment.addToClasspath(rtJar);
|
||||
|
||||
VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(arguments.src);
|
||||
if (vFile == null) {
|
||||
System.out.print("File/directory not found: " + arguments.src);
|
||||
return;
|
||||
}
|
||||
|
||||
Project project = environment.getProject();
|
||||
GenerationState generationState = new GenerationState(project, false);
|
||||
List<JetNamespace> namespaces = Lists.newArrayList();
|
||||
if(vFile.isDirectory()) {
|
||||
File dir = new File(vFile.getPath());
|
||||
addFiles(environment, project, namespaces, dir);
|
||||
final File unpackedRuntimePath = getUnpackedRuntimePath();
|
||||
if (unpackedRuntimePath != null) {
|
||||
environment.addToClasspath(unpackedRuntimePath);
|
||||
}
|
||||
else {
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile);
|
||||
if (psiFile instanceof JetFile) {
|
||||
namespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
final File runtimeJarPath = getRuntimeJarPath();
|
||||
if (runtimeJarPath != null && runtimeJarPath.exists()) {
|
||||
environment.addToClasspath(runtimeJarPath);
|
||||
}
|
||||
else {
|
||||
System.out.print("Not a Kotlin file: " + vFile.getPath());
|
||||
System.out.println("No runtime library found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY);
|
||||
if (arguments.module != null) {
|
||||
compileModuleScript(environment, arguments.module);
|
||||
return;
|
||||
}
|
||||
|
||||
ErrorCollector errorCollector = new ErrorCollector(bindingContext);
|
||||
errorCollector.report();
|
||||
CompileSession session = new CompileSession(environment);
|
||||
session.addSources(arguments.src);
|
||||
|
||||
if (!errorCollector.hasErrors) {
|
||||
generationState.compileCorrectNamespaces(bindingContext, namespaces);
|
||||
|
||||
final ClassFileFactory factory = generationState.getFactory();
|
||||
if(arguments.outputDir == null) {
|
||||
System.out.println("Output directory is not specified - no files will be saved to the disk");
|
||||
String mainClass = null;
|
||||
for (JetNamespace namespace : session.getSourceFileNamespaces()) {
|
||||
if (JetMainDetector.hasMain(namespace.getDeclarations())) {
|
||||
mainClass = namespace.getFQName() + ".namespace";
|
||||
break;
|
||||
}
|
||||
else {
|
||||
List<String> files = factory.files();
|
||||
for (String file : files) {
|
||||
File target = new File(arguments.outputDir, file);
|
||||
}
|
||||
if (!session.analyze()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClassFileFactory factory = session.generate();
|
||||
if (arguments.jar != null) {
|
||||
writeToJar(factory, arguments.jar, mainClass, true);
|
||||
}
|
||||
else if (arguments.outputDir != null) {
|
||||
writeToOutputDirectory(factory, arguments.outputDir);
|
||||
}
|
||||
else {
|
||||
System.out.println("Output directory or jar file is not specified - no files will be saved to the disk");
|
||||
}
|
||||
}
|
||||
|
||||
private static void compileModuleScript(JetCoreEnvironment environment, String moduleFile) {
|
||||
CompileSession scriptCompileSession = new CompileSession(environment);
|
||||
scriptCompileSession.addSources(moduleFile);
|
||||
|
||||
URL url = KotlinCompiler.class.getClassLoader().getResource("ModuleBuilder.kt");
|
||||
if (url != null) {
|
||||
String path = url.getPath();
|
||||
if (path.startsWith("file:")) {
|
||||
path = path.substring(5);
|
||||
}
|
||||
final VirtualFile vFile = environment.getJarFileSystem().findFileByPath(path);
|
||||
if (vFile == null) {
|
||||
System.out.println("Couldn't load ModuleBuilder.kt from runtime jar: "+ url);
|
||||
return;
|
||||
}
|
||||
scriptCompileSession.addSources(vFile);
|
||||
}
|
||||
else {
|
||||
// building from source
|
||||
final String homeDirectory = getHomeDirectory();
|
||||
final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt");
|
||||
scriptCompileSession.addSources(environment.getLocalFileSystem().findFileByPath(file.getPath()));
|
||||
}
|
||||
|
||||
if (!scriptCompileSession.analyze()) {
|
||||
return;
|
||||
}
|
||||
final ClassFileFactory factory = scriptCompileSession.generate();
|
||||
|
||||
final IModuleSetBuilder moduleSetBuilder = runDefineModules(moduleFile, factory);
|
||||
|
||||
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) {
|
||||
compileModule(environment, moduleBuilder, new File(moduleFile).getParent());
|
||||
}
|
||||
}
|
||||
|
||||
private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) {
|
||||
GeneratedClassLoader loader = new GeneratedClassLoader(factory);
|
||||
try {
|
||||
Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder");
|
||||
final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance();
|
||||
|
||||
Class namespaceClass = loader.loadClass("namespace");
|
||||
final Method[] methods = namespaceClass.getMethods();
|
||||
boolean modulesDefined = false;
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals("defineModules")) {
|
||||
method.invoke(null, moduleSetBuilder);
|
||||
modulesDefined = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!modulesDefined) {
|
||||
System.out.println("Module script " + moduleFile + " must define a defineModules() method");
|
||||
return null;
|
||||
}
|
||||
return moduleSetBuilder;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void compileModule(JetCoreEnvironment environment, IModuleBuilder moduleBuilder, String directory) {
|
||||
CompileSession moduleCompileSession = new CompileSession(environment);
|
||||
for (String sourceFile : moduleBuilder.getSourceFiles()) {
|
||||
moduleCompileSession.addSources(new File(directory, sourceFile).getPath());
|
||||
}
|
||||
for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
|
||||
environment.addToClasspath(new File(classpathRoot));
|
||||
}
|
||||
if (!moduleCompileSession.analyze()) {
|
||||
return;
|
||||
}
|
||||
ClassFileFactory factory = moduleCompileSession.generate();
|
||||
writeToJar(factory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true);
|
||||
}
|
||||
|
||||
private static String getHomeDirectory() {
|
||||
return new File(PathManager.getResourceRoot(KotlinCompiler.class, "/org/jetbrains/jet/cli/KotlinCompiler.class")).getParentFile().getParentFile().getParent();
|
||||
}
|
||||
|
||||
private static void writeToJar(ClassFileFactory factory, String jar, String mainClass, boolean includeRuntime) {
|
||||
try {
|
||||
Manifest manifest = new Manifest();
|
||||
final Attributes mainAttributes = manifest.getMainAttributes();
|
||||
mainAttributes.putValue("Manifest-Version", "1.0");
|
||||
mainAttributes.putValue("Created-By", "JetBrains Kotlin");
|
||||
if (mainClass != null) {
|
||||
mainAttributes.putValue("Main-Class", mainClass);
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(jar);
|
||||
JarOutputStream stream = new JarOutputStream(fos, manifest);
|
||||
try {
|
||||
for (String file : factory.files()) {
|
||||
stream.putNextEntry(new JarEntry(file));
|
||||
stream.write(factory.asBytes(file));
|
||||
}
|
||||
if (includeRuntime) {
|
||||
writeRuntimeToJar(stream);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
System.out.println("Failed to generate jar file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static File getUnpackedRuntimePath() {
|
||||
URL url = KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class");
|
||||
if (url != null && url.getProtocol().equals("file")) {
|
||||
return new File(url.getPath()).getParentFile().getParentFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static File getRuntimeJarPath() {
|
||||
URL url = KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class");
|
||||
if (url != null && url.getProtocol().equals("jar")) {
|
||||
String path = url.getPath();
|
||||
return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/")));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void writeRuntimeToJar(final JarOutputStream stream) throws IOException {
|
||||
final File unpackedRuntimePath = getUnpackedRuntimePath();
|
||||
if (unpackedRuntimePath != null) {
|
||||
FileUtil.processFilesRecursively(unpackedRuntimePath, new Processor<File>() {
|
||||
@Override
|
||||
public boolean process(File file) {
|
||||
if (file.isDirectory()) return true;
|
||||
final String relativePath = FileUtil.getRelativePath(unpackedRuntimePath, file);
|
||||
try {
|
||||
FileUtil.writeToFile(target, factory.asBytes(file));
|
||||
System.out.println("Generated classfile: " + target);
|
||||
stream.putNextEntry(new JarEntry(FileUtil.toSystemIndependentName(relativePath)));
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
try {
|
||||
FileUtil.copy(fis, stream);
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ErrorCollector {
|
||||
Multimap<PsiFile,DiagnosticWithTextRange> maps = LinkedHashMultimap.<PsiFile, DiagnosticWithTextRange>create();
|
||||
|
||||
boolean hasErrors;
|
||||
|
||||
public ErrorCollector(BindingContext bindingContext) {
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
report(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
private void report(Diagnostic diagnostic) {
|
||||
hasErrors |= diagnostic.getSeverity() == Severity.ERROR;
|
||||
if(diagnostic instanceof DiagnosticWithTextRange) {
|
||||
DiagnosticWithTextRange diagnosticWithTextRange = (DiagnosticWithTextRange) diagnostic;
|
||||
maps.put(diagnosticWithTextRange.getPsiFile(), diagnosticWithTextRange);
|
||||
}
|
||||
else {
|
||||
System.out.println(diagnostic.getSeverity().toString() + ": " + diagnostic.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void report() {
|
||||
if(!maps.isEmpty()) {
|
||||
for (PsiFile psiFile : maps.keySet()) {
|
||||
System.out.println(psiFile.getVirtualFile().getPath());
|
||||
Collection<DiagnosticWithTextRange> diagnosticWithTextRanges = maps.get(psiFile);
|
||||
for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) {
|
||||
String position = DiagnosticUtils.formatPosition(diagnosticWithTextRange);
|
||||
System.out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage());
|
||||
else {
|
||||
File runtimeJarPath = getRuntimeJarPath();
|
||||
if (runtimeJarPath != null) {
|
||||
JarInputStream jis = new JarInputStream(new FileInputStream(runtimeJarPath));
|
||||
try {
|
||||
while (true) {
|
||||
JarEntry e = jis.getNextJarEntry();
|
||||
if (e == null) {
|
||||
break;
|
||||
}
|
||||
if (FileUtil.getExtension(e.getName()).equals("class")) {
|
||||
stream.putNextEntry(e);
|
||||
FileUtil.copy(jis, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void addFiles(JavaCoreEnvironment environment, Project project, List<JetNamespace> namespaces, File dir) {
|
||||
for(File file : dir.listFiles()) {
|
||||
if(!file.isDirectory()) {
|
||||
VirtualFile virtualFile = environment.getLocalFileSystem().findFileByPath(file.getAbsolutePath());
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
|
||||
if (psiFile instanceof JetFile) {
|
||||
namespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
} finally {
|
||||
jis.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
addFiles(environment, project, namespaces, file);
|
||||
System.out.println("Couldn't find runtime library");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) {
|
||||
List<String> files = factory.files();
|
||||
for (String file : files) {
|
||||
File target = new File(outputDir, file);
|
||||
try {
|
||||
FileUtil.writeToFile(target, factory.asBytes(file));
|
||||
System.out.println("Generated classfile: " + target);
|
||||
} catch (IOException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,85 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class AnalyzerFacade {
|
||||
|
||||
public static final Function<JetFile, Collection<JetDeclaration>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
|
||||
@Override
|
||||
public Collection<JetDeclaration> fun(JetFile file) {
|
||||
return Collections.<JetDeclaration>singleton(file.getRootNamespace());
|
||||
}
|
||||
};
|
||||
|
||||
private static final AnalyzingUtils ANALYZING_UTILS = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS);
|
||||
private final static Key<CachedValue<BindingContext>> BINDING_CONTEXT = Key.create("BINDING_CONTEXT");
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
return AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespace(namespace, flowDataTraceFactory);
|
||||
return ANALYZING_UTILS.analyzeNamespace(namespace, flowDataTraceFactory);
|
||||
}
|
||||
|
||||
public static BindingContext analyzeFileWithCache(@NotNull JetFile file) {
|
||||
return AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeFileWithCache(file);
|
||||
public static BindingContext analyzeFileWithCache(@NotNull final JetFile file, @NotNull final Function<JetFile, Collection<JetDeclaration>> declarationProvider) {
|
||||
return analyzeFileWithCache(ANALYZING_UTILS, file, declarationProvider);
|
||||
}
|
||||
|
||||
public static BindingContext analyzeFileWithCache(@NotNull final AnalyzingUtils analyzingUtils,
|
||||
@NotNull final JetFile file,
|
||||
@NotNull final Function<JetFile, Collection<JetDeclaration>> declarationProvider) {
|
||||
// TODO : Synchronization?
|
||||
CachedValue<BindingContext> bindingContextCachedValue = file.getUserData(BINDING_CONTEXT);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<BindingContext>() {
|
||||
@Override
|
||||
public Result<BindingContext> compute() {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
BindingContext bindingContext = analyzingUtils.analyzeNamespaces(
|
||||
file.getProject(),
|
||||
declarationProvider.fun(file),
|
||||
Predicates.<PsiFile>equalTo(file),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
return new Result<BindingContext>(bindingContext, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||
return new Result<BindingContext>(bindingTraceContext.getBindingContext(), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, false);
|
||||
file.putUserData(BINDING_CONTEXT, bindingContextCachedValue);
|
||||
}
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-2
@@ -300,15 +300,26 @@ public class JavaDescriptorResolver {
|
||||
for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
String name = parameter.getName();
|
||||
PsiType psiType = parameter.getType();
|
||||
|
||||
JetType varargElementType;
|
||||
if (psiType instanceof PsiEllipsisType) {
|
||||
PsiEllipsisType psiEllipsisType = (PsiEllipsisType) psiType;
|
||||
varargElementType = semanticServices.getTypeTransformer().transformToType(psiEllipsisType.getComponentType());
|
||||
}
|
||||
else {
|
||||
varargElementType = null;
|
||||
}
|
||||
JetType outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||
result.add(new ValueParameterDescriptorImpl(
|
||||
containingDeclaration,
|
||||
i,
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
name == null ? "p" + i : name,
|
||||
null, // TODO : review
|
||||
semanticServices.getTypeTransformer().transformToType(parameter.getType()),
|
||||
outType,
|
||||
false,
|
||||
parameter.isVarArgs()
|
||||
varargElementType
|
||||
));
|
||||
}
|
||||
return result;
|
||||
|
||||
+4
-30
@@ -16,35 +16,6 @@ import java.util.*;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class FunctionDescriptorUtil {
|
||||
/** @return Minimal number of arguments to be passed */
|
||||
public static int getMinimumArity(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
int result = 0;
|
||||
for (ValueParameterDescriptor valueParameter : functionDescriptor.getValueParameters()) {
|
||||
if (valueParameter.hasDefaultValue()) {
|
||||
break;
|
||||
}
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum number of arguments that can be passed. -1 if unbound (vararg)
|
||||
*/
|
||||
public static int getMaximumArity(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters();
|
||||
if (unsubstitutedValueParameters.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
// TODO : check somewhere that vararg is only the last one, and that varargs do not have default values
|
||||
|
||||
ValueParameterDescriptor lastParameter = unsubstitutedValueParameters.get(unsubstitutedValueParameters.size() - 1);
|
||||
if (lastParameter.isVararg()) {
|
||||
return -1;
|
||||
}
|
||||
return unsubstitutedValueParameters.size();
|
||||
}
|
||||
|
||||
public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
|
||||
if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
|
||||
|
||||
@@ -69,13 +40,16 @@ public class FunctionDescriptorUtil {
|
||||
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
|
||||
// TODO : Lazy?
|
||||
JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getOutType(), Variance.IN_VARIANCE);
|
||||
JetType varargElementType = unsubstitutedValueParameter.getVarargElementType();
|
||||
JetType substituteVarargElementType = varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
|
||||
if (substitutedType == null) return null;
|
||||
result.add(new ValueParameterDescriptorImpl(
|
||||
substitutedDescriptor,
|
||||
unsubstitutedValueParameter,
|
||||
unsubstitutedValueParameter.getAnnotations(),
|
||||
unsubstitutedValueParameter.getInType() == null ? null : substitutedType,
|
||||
substitutedType
|
||||
substitutedType,
|
||||
substituteVarargElementType
|
||||
));
|
||||
}
|
||||
return result;
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
/**
|
||||
@@ -15,7 +16,7 @@ public interface ValueParameterDescriptor extends VariableDescriptor {
|
||||
int getIndex();
|
||||
boolean hasDefaultValue();
|
||||
boolean isRef();
|
||||
boolean isVararg();
|
||||
@Nullable JetType getVarargElementType();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -26,4 +27,5 @@ public interface ValueParameterDescriptor extends VariableDescriptor {
|
||||
|
||||
@NotNull
|
||||
ValueParameterDescriptor copy(DeclarationDescriptor newOwner);
|
||||
|
||||
}
|
||||
|
||||
+10
-9
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
*/
|
||||
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
|
||||
private final boolean hasDefaultValue;
|
||||
private final boolean isVararg;
|
||||
private final JetType varargElementType;
|
||||
private final boolean isVar;
|
||||
private final int index;
|
||||
private final ValueParameterDescriptor original;
|
||||
@@ -27,12 +27,12 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
@Nullable JetType inType,
|
||||
@NotNull JetType outType,
|
||||
boolean hasDefaultValue,
|
||||
boolean isVararg) {
|
||||
@Nullable JetType varargElementType) {
|
||||
super(containingDeclaration, annotations, name, inType, outType);
|
||||
this.original = this;
|
||||
this.index = index;
|
||||
this.hasDefaultValue = hasDefaultValue;
|
||||
this.isVararg = isVararg;
|
||||
this.varargElementType = varargElementType;
|
||||
this.isVar = inType != null;
|
||||
}
|
||||
|
||||
@@ -41,13 +41,14 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
@NotNull ValueParameterDescriptor original,
|
||||
@NotNull List<AnnotationDescriptor> annotations,
|
||||
@Nullable JetType inType,
|
||||
@NotNull JetType outType
|
||||
@NotNull JetType outType,
|
||||
@Nullable JetType varargElementType
|
||||
) {
|
||||
super(containingDeclaration, annotations, original.getName(), inType, outType);
|
||||
this.original = original;
|
||||
this.index = original.getIndex();
|
||||
this.hasDefaultValue = original.hasDefaultValue();
|
||||
this.isVararg = original.isVararg();
|
||||
this.varargElementType = varargElementType;
|
||||
this.isVar = inType != null;
|
||||
}
|
||||
|
||||
@@ -76,9 +77,9 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVararg() {
|
||||
return isVararg;
|
||||
@Nullable
|
||||
public JetType getVarargElementType() {
|
||||
return varargElementType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -106,6 +107,6 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
@NotNull
|
||||
@Override
|
||||
public ValueParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
|
||||
return new ValueParameterDescriptorImpl(newOwner, index, Lists.newArrayList(getAnnotations()), getName(), getInType(), getOutType(), hasDefaultValue, isVararg);
|
||||
return new ValueParameterDescriptorImpl(newOwner, index, Lists.newArrayList(getAnnotations()), getName(), getInType(), getOutType(), hasDefaultValue, varargElementType);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -15,8 +15,8 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR;
|
||||
public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiElement> {
|
||||
public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl<PsiElement> implements RedeclarationDiagnostic {
|
||||
|
||||
public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement) {
|
||||
super(RedeclarationDiagnosticFactory.INSTANCE, ERROR, "Redeclaration", psiElement);
|
||||
public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name) {
|
||||
super(RedeclarationDiagnosticFactory.INSTANCE, ERROR, "Redeclaration: " + name, psiElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiEle
|
||||
@NotNull
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Redeclaration";
|
||||
return "Redeclaration: " + duplicatingDescriptor.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@ public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
|
||||
|
||||
public RedeclarationDiagnosticFactory() {}
|
||||
|
||||
public RedeclarationDiagnostic on(@NotNull PsiElement duplicatingElement) {
|
||||
return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement);
|
||||
public RedeclarationDiagnostic on(@NotNull PsiElement duplicatingElement, @NotNull String name) {
|
||||
return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement, name);
|
||||
}
|
||||
|
||||
public Diagnostic on(DeclarationDescriptor duplicatingDescriptor, BindingContext contextToResolveToDeclaration) {
|
||||
|
||||
@@ -167,7 +167,7 @@ public class JetParsing extends AbstractJetParsing {
|
||||
}
|
||||
|
||||
PsiBuilder.Marker reference = mark();
|
||||
expect(IDENTIFIER, "Expecting qualified name", TokenSet.create(DOT, AS_KEYWORD));
|
||||
expect(IDENTIFIER, "Expecting qualified name");
|
||||
reference.done(REFERENCE_EXPRESSION);
|
||||
while (at(DOT) && lookahead(1) != MUL) {
|
||||
advance(); // DOT
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
@@ -105,17 +104,6 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
|
||||
return body.getProperties();
|
||||
}
|
||||
|
||||
public String getFQName() {
|
||||
JetNamedDeclaration parent = PsiTreeUtil.getParentOfType(this, JetNamespace.class, JetClass.class);
|
||||
if (parent instanceof JetNamespace) {
|
||||
return ((JetNamespace) parent).getFQName() + "." + getName();
|
||||
}
|
||||
if (parent instanceof JetClass) {
|
||||
return ((JetClass) parent).getFQName() + "." + getName();
|
||||
}
|
||||
return getName();
|
||||
}
|
||||
|
||||
public boolean isTrait() {
|
||||
return findChildByType(JetTokens.TRAIT_KEYWORD) != null;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,11 @@ public class JetParameter extends JetNamedDeclaration {
|
||||
return findChildByType(JetTokens.VAR_KEYWORD) != null || isRef();
|
||||
}
|
||||
|
||||
public boolean isVarArg() {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
return modifierList != null && modifierList.getModifierNode(JetTokens.VARARG_KEYWORD) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ASTNode getValOrVarNode() {
|
||||
ASTNode val = getNode().findChildByType(JetTokens.VAL_KEYWORD);
|
||||
|
||||
@@ -1,40 +1,33 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
//import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
|
||||
//import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class AnalyzingUtils {
|
||||
private final static Key<CachedValue<BindingContext>> BINDING_CONTEXT = Key.create("BINDING_CONTEXT");
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static AnalyzingUtils getInstance(@NotNull ImportingStrategy importingStrategy) {
|
||||
return new AnalyzingUtils(importingStrategy);
|
||||
}
|
||||
@@ -69,17 +62,24 @@ public class AnalyzingUtils {
|
||||
Project project = namespace.getProject();
|
||||
List<JetDeclaration> declarations = Collections.<JetDeclaration>singletonList(namespace);
|
||||
|
||||
return analyzeNamespaces(project, declarations, flowDataTraceFactory);
|
||||
return analyzeNamespaces(project, declarations, Predicates.equalTo(namespace.getContainingFile()), flowDataTraceFactory);
|
||||
}
|
||||
|
||||
public BindingContext analyzeNamespaces(@NotNull Project project, @NotNull List<? extends JetDeclaration> declarations, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
public BindingContext analyzeNamespaces(
|
||||
@NotNull Project project,
|
||||
@NotNull Collection<? extends JetDeclaration> declarations,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project);
|
||||
|
||||
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope();
|
||||
ModuleDescriptor owner = new ModuleDescriptor("<module>");
|
||||
final WritableScope scope = new WritableScopeImpl(libraryScope, owner, new TraceBasedRedeclarationHandler(bindingTraceContext)).setDebugName("Root scope in analyzeNamespace");
|
||||
|
||||
final WritableScope scope = new WritableScopeImpl(JetScope.EMPTY, owner, new TraceBasedRedeclarationHandler(bindingTraceContext)).setDebugName("Root scope in analyzeNamespace");
|
||||
importingStrategy.addImports(project, semanticServices, bindingTraceContext, scope);
|
||||
scope.importScope(libraryScope);
|
||||
|
||||
TopDownAnalyzer.process(semanticServices, bindingTraceContext, scope, new NamespaceLike.Adapter(owner) {
|
||||
|
||||
@Override
|
||||
@@ -111,38 +111,8 @@ public class AnalyzingUtils {
|
||||
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
|
||||
}
|
||||
}, declarations, flowDataTraceFactory);
|
||||
}, declarations, filesToAnalyzeCompletely, flowDataTraceFactory);
|
||||
return bindingTraceContext.getBindingContext();
|
||||
}
|
||||
|
||||
public BindingContext analyzeFileWithCache(@NotNull final JetFile file) {
|
||||
// TODO : Synchronization?
|
||||
CachedValue<BindingContext> bindingContextCachedValue = file.getUserData(BINDING_CONTEXT);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<BindingContext>() {
|
||||
@Override
|
||||
public Result<BindingContext> compute() {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
JetNamespace rootNamespace = file.getRootNamespace();
|
||||
BindingContext bindingContext = analyzeNamespace(rootNamespace, JetControlFlowDataTraceFactory.EMPTY);
|
||||
return new Result<BindingContext>(bindingContext, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
// bindingTraceContext.getErrorHandler().genericError(file.getNode(), e.getClass().getSimpleName() + ": " + e.getMessage());
|
||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||
return new Result<BindingContext>(bindingTraceContext.getBindingContext(), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
file.putUserData(BINDING_CONTEXT, bindingContextCachedValue);
|
||||
}
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class BindingContextUtils {
|
||||
private BindingContextUtils() {
|
||||
}
|
||||
|
||||
public static PsiElement resolveToDeclarationPsiElement(BindingContext bindingContext, JetReferenceExpression referenceExpression) {
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, referenceExpression);
|
||||
if (declarationDescriptor == null) {
|
||||
|
||||
@@ -71,7 +71,6 @@ public class BodyResolver {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void resolveBehaviorDeclarationBodies() {
|
||||
|
||||
resolveDelegationSpecifierLists();
|
||||
@@ -86,34 +85,6 @@ public class BodyResolver {
|
||||
computeDeferredTypes();
|
||||
}
|
||||
|
||||
private void computeDeferredTypes() {
|
||||
Collection<DeferredType> deferredTypes = context.getTrace().get(DEFERRED_TYPES, DEFERRED_TYPE_KEY);
|
||||
if (deferredTypes != null) {
|
||||
final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size());
|
||||
context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<BindingContext.DeferredTypeKey, DeferredType>() {
|
||||
@Override
|
||||
public void handleRecord(WritableSlice<BindingContext.DeferredTypeKey, DeferredType> deferredTypeKeyDeferredTypeWritableSlice, BindingContext.DeferredTypeKey key, DeferredType value) {
|
||||
queue.addLast(value);
|
||||
}
|
||||
});
|
||||
for (DeferredType deferredType : deferredTypes) {
|
||||
queue.addLast(deferredType);
|
||||
}
|
||||
while (!queue.isEmpty()) {
|
||||
DeferredType deferredType = queue.pullFirst();
|
||||
if (!deferredType.isComputed()) {
|
||||
try {
|
||||
deferredType.getActualType(); // to compute
|
||||
}
|
||||
catch (ReenteringLazyValueComputationException e) {
|
||||
// A problem should be reported while computing the type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void resolveDelegationSpecifierLists() {
|
||||
// TODO : Make sure the same thing is not initialized twice
|
||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||
@@ -125,6 +96,7 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolveDelegationSpecifierList(final JetClassOrObject jetClass, final MutableClassDescriptor descriptor) {
|
||||
if (!context.completeAnalysisNeeded(jetClass)) return;
|
||||
final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
|
||||
final JetScope scopeForConstructor = primaryConstructor == null
|
||||
? null
|
||||
@@ -278,7 +250,6 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolveClassAnnotations() {
|
||||
|
||||
}
|
||||
|
||||
private void resolveAnonymousInitializers() {
|
||||
@@ -291,6 +262,7 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolveAnonymousInitializers(JetClassOrObject jetClassOrObject, MutableClassDescriptor classDescriptor) {
|
||||
if (!context.completeAnalysisNeeded(jetClassOrObject)) return;
|
||||
List<JetClassInitializer> anonymousInitializers = jetClassOrObject.getAnonymousInitializers();
|
||||
if (jetClassOrObject.hasPrimaryConstructor()) {
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
@@ -320,6 +292,7 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor descriptor, final JetScope declaringScope) {
|
||||
if (!context.completeAnalysisNeeded(declaration)) return;
|
||||
final JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope, false);
|
||||
|
||||
final CallResolver callResolver = new CallResolver(context.getSemanticServices(), DataFlowInfo.EMPTY); // TODO: dataFlowInfo
|
||||
@@ -419,6 +392,7 @@ public class BodyResolver {
|
||||
Set<JetProperty> processed = Sets.newHashSet();
|
||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||
JetClass jetClass = entry.getKey();
|
||||
if (!context.completeAnalysisNeeded(jetClass)) continue;
|
||||
MutableClassDescriptor classDescriptor = entry.getValue();
|
||||
|
||||
for (JetProperty property : jetClass.getProperties()) {
|
||||
@@ -444,6 +418,7 @@ public class BodyResolver {
|
||||
// Top-level properties & properties of objects
|
||||
for (Map.Entry<JetProperty, PropertyDescriptor> entry : this.context.getProperties().entrySet()) {
|
||||
JetProperty property = entry.getKey();
|
||||
if (!context.completeAnalysisNeeded(property)) return;
|
||||
if (processed.contains(property)) continue;
|
||||
|
||||
final PropertyDescriptor propertyDescriptor = entry.getValue();
|
||||
@@ -540,6 +515,7 @@ public class BodyResolver {
|
||||
@NotNull JetDeclarationWithBody function,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull JetScope declaringScope) {
|
||||
if (!context.completeAnalysisNeeded(function)) return;
|
||||
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
@@ -564,4 +540,31 @@ public class BodyResolver {
|
||||
|
||||
assert functionDescriptor.getReturnType() != null;
|
||||
}
|
||||
|
||||
private void computeDeferredTypes() {
|
||||
Collection<DeferredType> deferredTypes = context.getTrace().get(DEFERRED_TYPES, DEFERRED_TYPE_KEY);
|
||||
if (deferredTypes != null) {
|
||||
final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size());
|
||||
context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<BindingContext.DeferredTypeKey, DeferredType>() {
|
||||
@Override
|
||||
public void handleRecord(WritableSlice<BindingContext.DeferredTypeKey, DeferredType> deferredTypeKeyDeferredTypeWritableSlice, BindingContext.DeferredTypeKey key, DeferredType value) {
|
||||
queue.addLast(value);
|
||||
}
|
||||
});
|
||||
for (DeferredType deferredType : deferredTypes) {
|
||||
queue.addLast(deferredType);
|
||||
}
|
||||
while (!queue.isEmpty()) {
|
||||
DeferredType deferredType = queue.pullFirst();
|
||||
if (!deferredType.isComputed()) {
|
||||
try {
|
||||
deferredType.getActualType(); // to compute
|
||||
}
|
||||
catch (ReenteringLazyValueComputationException e) {
|
||||
// A problem should be reported while computing the type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,21 +246,56 @@ public class ClassDescriptorResolver {
|
||||
|
||||
@NotNull
|
||||
public MutableValueParameterDescriptor resolveValueParameterDescriptor(DeclarationDescriptor declarationDescriptor, JetParameter valueParameter, int index, JetType type) {
|
||||
JetType varargElementType = null;
|
||||
JetType variableType = type;
|
||||
if (valueParameter.hasModifier(JetTokens.VARARG_KEYWORD)) {
|
||||
varargElementType = type;
|
||||
variableType = getVarargParameterType(type);
|
||||
}
|
||||
MutableValueParameterDescriptor valueParameterDescriptor = new ValueParameterDescriptorImpl(
|
||||
declarationDescriptor,
|
||||
index,
|
||||
annotationResolver.createAnnotationStubs(valueParameter.getModifierList()),
|
||||
JetPsiUtil.safeName(valueParameter.getName()),
|
||||
valueParameter.isMutable() ? type : null,
|
||||
type,
|
||||
valueParameter.isMutable() ? variableType : null,
|
||||
variableType,
|
||||
valueParameter.getDefaultValue() != null,
|
||||
valueParameter.hasModifier(JetTokens.VARARG_KEYWORD)
|
||||
varargElementType
|
||||
);
|
||||
|
||||
trace.record(BindingContext.VALUE_PARAMETER, valueParameter, valueParameterDescriptor);
|
||||
return valueParameterDescriptor;
|
||||
}
|
||||
|
||||
private JetType getVarargParameterType(JetType type) {
|
||||
JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
|
||||
if (type.equals(standardLibrary.getByteType())) {
|
||||
return standardLibrary.getByteArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getCharType())) {
|
||||
return standardLibrary.getCharArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getShortType())) {
|
||||
return standardLibrary.getShortArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getIntType())) {
|
||||
return standardLibrary.getIntArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getLongType())) {
|
||||
return standardLibrary.getLongArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getFloatType())) {
|
||||
return standardLibrary.getFloatArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getDoubleType())) {
|
||||
return standardLibrary.getDoubleArrayType();
|
||||
}
|
||||
if (type.equals(standardLibrary.getBooleanType())) {
|
||||
return standardLibrary.getBooleanArrayType();
|
||||
}
|
||||
return standardLibrary.getArrayType(type);
|
||||
}
|
||||
|
||||
public List<TypeParameterDescriptor> resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List<JetTypeParameter> typeParameters) {
|
||||
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
|
||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
||||
|
||||
@@ -46,6 +46,8 @@ public class ControlFlowAnalyzer {
|
||||
JetNamedFunction function = entry.getKey();
|
||||
FunctionDescriptorImpl functionDescriptor = entry.getValue();
|
||||
|
||||
if (!context.completeAnalysisNeeded(function)) continue;
|
||||
|
||||
final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType()
|
||||
? NO_EXPECTED_TYPE
|
||||
: functionDescriptor.getReturnType();
|
||||
|
||||
@@ -40,7 +40,8 @@ public class DeclarationsChecker {
|
||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
|
||||
JetClass aClass = entry.getKey();
|
||||
MutableClassDescriptor classDescriptor = entry.getValue();
|
||||
|
||||
if (!context.completeAnalysisNeeded(aClass)) continue;
|
||||
|
||||
checkClass(aClass, classDescriptor);
|
||||
checkModifiers(aClass.getModifierList());
|
||||
}
|
||||
@@ -50,6 +51,7 @@ public class DeclarationsChecker {
|
||||
JetObjectDeclaration objectDeclaration = entry.getKey();
|
||||
MutableClassDescriptor objectDescriptor = entry.getValue();
|
||||
|
||||
if (!context.completeAnalysisNeeded(objectDeclaration)) continue;
|
||||
checkObject(objectDeclaration, objectDescriptor);
|
||||
}
|
||||
|
||||
@@ -58,6 +60,7 @@ public class DeclarationsChecker {
|
||||
JetNamedFunction function = entry.getKey();
|
||||
FunctionDescriptorImpl functionDescriptor = entry.getValue();
|
||||
|
||||
if (!context.completeAnalysisNeeded(function)) continue;
|
||||
checkFunction(function, functionDescriptor);
|
||||
checkModifiers(function.getModifierList());
|
||||
}
|
||||
@@ -67,6 +70,7 @@ public class DeclarationsChecker {
|
||||
JetProperty property = entry.getKey();
|
||||
PropertyDescriptor propertyDescriptor = entry.getValue();
|
||||
|
||||
if (!context.completeAnalysisNeeded(property)) continue;
|
||||
checkProperty(property, propertyDescriptor);
|
||||
checkModifiers(property.getModifierList());
|
||||
}
|
||||
@@ -77,6 +81,7 @@ public class DeclarationsChecker {
|
||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||
MutableClassDescriptor classDescriptor = entry.getValue();
|
||||
JetClass jetClass = entry.getKey();
|
||||
if (!context.completeAnalysisNeeded(jetClass)) return;
|
||||
if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null && !(classDescriptor.getKind() == ClassKind.TRAIT)) {
|
||||
for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) {
|
||||
if (context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -32,10 +37,42 @@ import java.util.Set;
|
||||
private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
|
||||
private final Set<PropertyDescriptor> primaryConstructorParameterProperties = Sets.newHashSet();
|
||||
|
||||
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace) {
|
||||
private final Predicate<PsiFile> analyzeCompletely;
|
||||
|
||||
private StringBuilder debugOutput;
|
||||
|
||||
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate<PsiFile> analyzeCompletely) {
|
||||
this.trace = new ObservableBindingTrace(trace);
|
||||
this.semanticServices = semanticServices;
|
||||
this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
|
||||
this.analyzeCompletely = analyzeCompletely;
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
if (debugOutput != null) {
|
||||
debugOutput.append(message).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void enableDebugOutput() {
|
||||
if (debugOutput == null) {
|
||||
debugOutput = new StringBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void printDebugOutput(PrintStream out) {
|
||||
if (debugOutput != null) {
|
||||
out.print(debugOutput);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean completeAnalysisNeeded(@NotNull PsiElement element) {
|
||||
PsiFile containingFile = element.getContainingFile();
|
||||
boolean result = containingFile != null && analyzeCompletely.apply(containingFile);
|
||||
if (!result) {
|
||||
debug(containingFile);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ObservableBindingTrace getTrace() {
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -22,35 +28,43 @@ public class TopDownAnalyzer {
|
||||
@NotNull JetSemanticServices semanticServices,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope outerScope,
|
||||
NamespaceLike owner,
|
||||
@NotNull List<? extends JetDeclaration> declarations,
|
||||
@NotNull NamespaceLike owner,
|
||||
@NotNull Collection<? extends JetDeclaration> declarations,
|
||||
@NotNull Predicate<PsiFile> analyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
process(semanticServices, trace, outerScope, owner, declarations, flowDataTraceFactory, false);
|
||||
process(semanticServices, trace, outerScope, owner, declarations, analyzeCompletely, flowDataTraceFactory, false);
|
||||
}
|
||||
|
||||
private static void process(
|
||||
@NotNull JetSemanticServices semanticServices,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope outerScope,
|
||||
NamespaceLike owner,
|
||||
@NotNull List<? extends JetDeclaration> declarations,
|
||||
@NotNull NamespaceLike owner,
|
||||
@NotNull Collection<? extends JetDeclaration> declarations,
|
||||
@NotNull Predicate<PsiFile> analyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
boolean declaredLocally) {
|
||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
|
||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely);
|
||||
// context.enableDebugOutput();
|
||||
context.debug("Enter");
|
||||
|
||||
new TypeHierarchyResolver(context).process(outerScope, owner, declarations);
|
||||
new DeclarationResolver(context).process();
|
||||
new DelegationResolver(context).process();
|
||||
new OverrideResolver(context).process();
|
||||
new BodyResolver(context).resolveBehaviorDeclarationBodies();
|
||||
new ControlFlowAnalyzer(context, flowDataTraceFactory, declaredLocally).process();
|
||||
new DeclarationsChecker(context).process();
|
||||
new DeclarationsChecker(context).process();
|
||||
|
||||
context.debug("Exit");
|
||||
context.printDebugOutput(System.out);
|
||||
}
|
||||
|
||||
public static void processStandardLibraryNamespace(
|
||||
@NotNull JetSemanticServices semanticServices,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull JetNamespace namespace) {
|
||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
|
||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.<PsiFile>alwaysTrue());
|
||||
context.getNamespaceScopes().put(namespace, standardLibraryNamespace.getMemberScope());
|
||||
context.getNamespaceDescriptors().put(namespace, standardLibraryNamespace);
|
||||
context.getDeclaringScopes().put(namespace, outerScope);
|
||||
@@ -104,7 +118,7 @@ public class TopDownAnalyzer {
|
||||
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||
return ClassObjectStatus.NOT_ALLOWED;
|
||||
}
|
||||
}, Collections.<JetDeclaration>singletonList(object), JetControlFlowDataTraceFactory.EMPTY, true);
|
||||
}, Collections.<JetDeclaration>singletonList(object), Predicates.equalTo(object.getContainingFile()), JetControlFlowDataTraceFactory.EMPTY, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ public class TraceBasedRedeclarationHandler implements RedeclarationHandler {
|
||||
private void report(DeclarationDescriptor first) {
|
||||
PsiElement firstElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, first);
|
||||
if (firstElement != null) {
|
||||
trace.report(REDECLARATION.on(firstElement));
|
||||
trace.report(REDECLARATION.on(firstElement, first.getName()));
|
||||
}
|
||||
else {
|
||||
trace.report(REDECLARATION.on(first, trace.getBindingContext()));
|
||||
|
||||
@@ -36,7 +36,7 @@ public class TypeHierarchyResolver {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List<? extends JetDeclaration> declarations) {
|
||||
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
|
||||
collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes
|
||||
|
||||
processTypeImports();
|
||||
|
||||
@@ -387,13 +387,15 @@ public class CallResolver {
|
||||
ResolvedValueArgument valueArgument = entry.getValue();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
|
||||
|
||||
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor);
|
||||
|
||||
for (JetExpression expression : valueArgument.getArgumentExpressions()) {
|
||||
// JetExpression expression = valueArgument.getArgumentExpression();
|
||||
// TODO : more attempts, with different expected types
|
||||
ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, temporaryTrace);
|
||||
JetType type = temporaryServices.getType(scope, expression, NO_EXPECTED_TYPE);
|
||||
if (type != null) {
|
||||
constraintSystem.addSubtypingConstraint(type, valueParameterDescriptor.getOutType());
|
||||
constraintSystem.addSubtypingConstraint(type, effectiveExpectedType);
|
||||
}
|
||||
else {
|
||||
candidateCall.argumentHasNoType();
|
||||
@@ -512,6 +514,14 @@ public class CallResolver {
|
||||
return results;
|
||||
}
|
||||
|
||||
private JetType getEffectiveExpectedType(ValueParameterDescriptor valueParameterDescriptor) {
|
||||
JetType effectiveExpectedType = valueParameterDescriptor.getVarargElementType();
|
||||
if (effectiveExpectedType == null) {
|
||||
effectiveExpectedType = valueParameterDescriptor.getOutType();
|
||||
}
|
||||
return effectiveExpectedType;
|
||||
}
|
||||
|
||||
private void recordAutoCastIfNecessary(ReceiverDescriptor receiver, BindingTrace trace) {
|
||||
if (receiver instanceof AutoCastReceiver) {
|
||||
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) receiver;
|
||||
@@ -606,7 +616,7 @@ public class CallResolver {
|
||||
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
||||
ResolvedValueArgument resolvedArgument = entry.getValue();
|
||||
|
||||
JetType parameterType = parameterDescriptor.getOutType();
|
||||
JetType parameterType = getEffectiveExpectedType(parameterDescriptor);
|
||||
|
||||
List<JetExpression> argumentExpressions = resolvedArgument.getArgumentExpressions();
|
||||
for (JetExpression argumentExpression : argumentExpressions) {
|
||||
|
||||
+4
-4
@@ -84,7 +84,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
}
|
||||
else if (!valueParameters.isEmpty()) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||
if (valueParameterDescriptor.isVararg()) {
|
||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
|
||||
usedParameters.add(valueParameterDescriptor);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
}
|
||||
|
||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||
if (valueParameterDescriptor.isVararg()) {
|
||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||
// temporaryTrace.getErrorHandler().genericError(possiblyLabeledFunctionLiteral.getNode(), "Passing value as a vararg is only allowed inside a parenthesized argument list");
|
||||
temporaryTrace.report(VARARG_OUTSIDE_PARENTHESES.on(possiblyLabeledFunctionLiteral));
|
||||
error = true;
|
||||
@@ -154,7 +154,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
if (valueParameter.hasDefaultValue()) {
|
||||
candidateCall.recordValueArgument(valueParameter, DefaultValueArgument.DEFAULT);
|
||||
}
|
||||
else if (valueParameter.isVararg()) {
|
||||
else if (valueParameter.getVarargElementType() != null) {
|
||||
candidateCall.recordValueArgument(valueParameter, new VarargValueArgument());
|
||||
}
|
||||
else {
|
||||
@@ -182,7 +182,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
}
|
||||
|
||||
private static <D extends CallableDescriptor> void put(ResolvedCallImpl<D> candidateCall, ValueParameterDescriptor valueParameterDescriptor, ValueArgument valueArgument, Map<ValueParameterDescriptor, VarargValueArgument> varargs) {
|
||||
if (valueParameterDescriptor.isVararg()) {
|
||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||
VarargValueArgument vararg = varargs.get(valueParameterDescriptor);
|
||||
if (vararg == null) {
|
||||
vararg = new VarargValueArgument();
|
||||
|
||||
@@ -147,7 +147,7 @@ public class ErrorUtils {
|
||||
ERROR_PARAMETER_TYPE,
|
||||
ERROR_PARAMETER_TYPE,
|
||||
false,
|
||||
false));
|
||||
null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ public class JetStandardClasses {
|
||||
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
|
||||
for (int i = first; i <= last; i++) {
|
||||
JetType parameterType = arguments.get(i).getType();
|
||||
ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(functionDescriptor, i, Collections.<AnnotationDescriptor>emptyList(), "p" + i, null, parameterType, false, false);
|
||||
ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(functionDescriptor, i, Collections.<AnnotationDescriptor>emptyList(), "p" + i, null, parameterType, false, null);
|
||||
valueParameters.add(valueParameterDescriptor);
|
||||
}
|
||||
return valueParameters;
|
||||
|
||||
@@ -316,8 +316,8 @@ public class JetStandardLibrary {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType getArrayType(@NotNull Variance variance, @NotNull JetType argument) {
|
||||
List<TypeProjection> types = Collections.singletonList(new TypeProjection(variance, argument));
|
||||
public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) {
|
||||
List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
|
||||
return new JetTypeImpl(
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
getArray().getTypeConstructor(),
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (functionTypeExpected && declaredValueParameters.isEmpty() && expectedValueParameters.size() == 1) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0);
|
||||
ValueParameterDescriptor it = new ValueParameterDescriptorImpl(
|
||||
functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), "it", valueParameterDescriptor.getInType(), valueParameterDescriptor.getOutType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.isVararg()
|
||||
functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), "it", valueParameterDescriptor.getInType(), valueParameterDescriptor.getOutType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()
|
||||
);
|
||||
valueParameterDescriptors.add(it);
|
||||
parameterTypes.add(it.getOutType());
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.jetbrains.jet.plugin;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetParameter;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class JetMainDetector {
|
||||
private JetMainDetector() {
|
||||
}
|
||||
|
||||
public static boolean hasMain(List<JetDeclaration> declarations) {
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction) declaration;
|
||||
if ("main".equals(function.getName())) {
|
||||
List<JetParameter> parameters = function.getValueParameters();
|
||||
if (parameters.size() == 1) {
|
||||
JetTypeReference reference = parameters.get(0).getTypeReference();
|
||||
if (reference != null && reference.getText().equals("Array<String>")) { // TODO correct check
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public class DescriptorRenderer implements Renderer {
|
||||
@Override
|
||||
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
|
||||
builder.append(renderKeyword("value-parameter")).append(" ");
|
||||
if (descriptor.isVararg()) {
|
||||
if (descriptor.getVarargElementType() != null) {
|
||||
builder.append(renderKeyword("vararg")).append(" ");
|
||||
}
|
||||
return super.visitValueParameterDescriptor(descriptor, builder);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// KT-389 Wrong type inference for varargs etc.
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun foob(vararg a : Byte) : ByteArray = a
|
||||
fun fooc(vararg a : Char) : CharArray = a
|
||||
fun foos(vararg a : Short) : ShortArray = a
|
||||
fun fooi(vararg a : Int) : IntArray = a
|
||||
fun fool(vararg a : Long) : LongArray = a
|
||||
fun food(vararg a : Double) : DoubleArray = a
|
||||
fun foof(vararg a : Float) : FloatArray = a
|
||||
fun foob(vararg a : Boolean) : BooleanArray = a
|
||||
fun foos(vararg a : String) : Array<String> = a
|
||||
|
||||
fun test() {
|
||||
Arrays.asList(1, 2, 3)
|
||||
Arrays.asList<Int>(1, 2, 3)
|
||||
|
||||
foob(1, 2, 3)
|
||||
foos(1, 2, 3)
|
||||
fooc('1', '2', '3')
|
||||
fooi(1, 2, 3)
|
||||
fool(1, 2, 3)
|
||||
food(1.0, 2.0, 3.0)
|
||||
foof(1.0.flt, 2.0.flt, 3.0.flt)
|
||||
}
|
||||
@@ -10,3 +10,14 @@ namespace b {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace c {
|
||||
import d.X
|
||||
val x : X = X()
|
||||
}
|
||||
|
||||
namespace d {
|
||||
class X() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// KT-127 Support extension functions in when expressions
|
||||
|
||||
class Foo() {}
|
||||
|
||||
fun Any.equals(other : Any?) : Boolean = true
|
||||
fun Any?.equals1(other : Any?) : Boolean = true
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
val command : Foo? = null
|
||||
when (command) {
|
||||
.equals(null) => 1; // must be resolved
|
||||
?.equals(null) => 1 // same here
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// KT-128 Support passing only the last closure if all the other parameters have default values
|
||||
|
||||
fun div(c : String = "", f : fun()) {}
|
||||
fun f() {
|
||||
div { // Nothing passed, but could have been...
|
||||
// ...
|
||||
}
|
||||
|
||||
div (c = "foo") { // More things could have been passed
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// KT-26 Import namespaces defined in this file
|
||||
|
||||
namespace foo {
|
||||
import bar.* // Must not be an error
|
||||
}
|
||||
|
||||
namespace bar {}
|
||||
@@ -0,0 +1,10 @@
|
||||
// KT-26 Import namespaces defined in this file
|
||||
|
||||
import html.* // Must not be an error
|
||||
|
||||
namespace html {
|
||||
|
||||
abstract class Factory<T> {
|
||||
fun create() : T? = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// KT-282 Nullability in extension functions and in binary calls
|
||||
|
||||
class Set {
|
||||
fun contains(x : Int) : Boolean = true
|
||||
}
|
||||
|
||||
fun Set?.plus(x : Int) : Int = 1
|
||||
|
||||
fun Int?.contains(x : Int) : Boolean = false
|
||||
|
||||
fun f(): Unit {
|
||||
var set : Set? = null
|
||||
val i : Int? = null
|
||||
i <!UNSAFE_INFIX_CALL!>+<!> 1
|
||||
set + 1
|
||||
1 <!UNSAFE_INFIX_CALL!>in<!> set
|
||||
1 in 2
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fun box() : String {
|
||||
var a = 10
|
||||
return if(a?.plus(10) == 20) "OK" else "fail"
|
||||
}
|
||||
@@ -18,7 +18,8 @@ JetFile: Imports_ERR.jet
|
||||
PsiWhiteSpace(' ')
|
||||
REFERENCE_EXPRESSION
|
||||
PsiErrorElement:Expecting qualified name
|
||||
PsiElement(SEMICOLON)(';')
|
||||
<empty list>
|
||||
PsiElement(SEMICOLON)(';')
|
||||
PsiWhiteSpace('\n')
|
||||
IMPORT_DIRECTIVE
|
||||
PsiElement(import)('import')
|
||||
@@ -27,7 +28,9 @@ JetFile: Imports_ERR.jet
|
||||
PsiElement(DOT)('.')
|
||||
REFERENCE_EXPRESSION
|
||||
PsiErrorElement:Expecting qualified name
|
||||
PsiElement(MUL)('*')
|
||||
<empty list>
|
||||
PsiErrorElement:Expecting namespace or top level declaration
|
||||
PsiElement(MUL)('*')
|
||||
PsiWhiteSpace('\n')
|
||||
IMPORT_DIRECTIVE
|
||||
PsiElement(import)('import')
|
||||
@@ -37,7 +40,8 @@ JetFile: Imports_ERR.jet
|
||||
PsiWhiteSpace(' ')
|
||||
REFERENCE_EXPRESSION
|
||||
PsiErrorElement:Expecting qualified name
|
||||
PsiElement(SEMICOLON)(';')
|
||||
<empty list>
|
||||
PsiElement(SEMICOLON)(';')
|
||||
PsiWhiteSpace('\n\n')
|
||||
IMPORT_DIRECTIVE
|
||||
PsiElement(import)('import')
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.ImportingStrategy;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -80,7 +81,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
|
||||
}
|
||||
|
||||
public void test(PsiFile psiFile) {
|
||||
BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache((JetFile) psiFile);
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), (JetFile) psiFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
|
||||
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
|
||||
|
||||
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
|
||||
|
||||
@@ -42,7 +42,7 @@ public class FullJetPsiCheckerTest extends JetLiteFixture {
|
||||
String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
|
||||
|
||||
myFile = createPsiFile(myName, clearText);
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(myFile);
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(myFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
|
||||
|
||||
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.ImportingStrategy;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -39,7 +40,7 @@ public class QuickJetPsiCheckerTest extends JetLiteFixture {
|
||||
|
||||
createAndCheckPsiFile(name, clearText);
|
||||
JetFile jetFile = (JetFile) myFile;
|
||||
BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache(jetFile);
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), jetFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
|
||||
|
||||
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
|
||||
@Override
|
||||
|
||||
@@ -88,7 +88,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
|
||||
|
||||
protected String blackBox() throws Exception {
|
||||
ClassFileFactory codegens = generateClassesInFile();
|
||||
CodegensClassLoader loader = new CodegensClassLoader(codegens);
|
||||
GeneratedClassLoader loader = new GeneratedClassLoader(codegens);
|
||||
|
||||
final JetNamespace namespace = myFile.getRootNamespace();
|
||||
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
|
||||
@@ -215,23 +215,4 @@ public abstract class CodegenTestCase extends JetLiteFixture {
|
||||
return super.loadClass(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CodegensClassLoader extends ClassLoader {
|
||||
private final ClassFileFactory state;
|
||||
|
||||
public CodegensClassLoader(ClassFileFactory state) {
|
||||
super(CodegenTestCase.class.getClassLoader());
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String file = name.replace('.', '/') + ".class";
|
||||
if (state.files().contains(file)) {
|
||||
byte[] bytes = state.asBytes(file);
|
||||
return defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,4 +207,9 @@ public class ControlStructuresTest extends CodegenTestCase {
|
||||
public void testKt299() throws Exception {
|
||||
blackBoxFile("regressions/kt299.jet");
|
||||
}
|
||||
|
||||
public void testKt416() throws Exception {
|
||||
blackBoxFile("regressions/kt416.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,22 +8,55 @@ import java.lang.reflect.Method;
|
||||
*/
|
||||
public class VarArgTest extends CodegenTestCase {
|
||||
public void testStringArray () throws InvocationTargetException, IllegalAccessException {
|
||||
/*
|
||||
loadText("fun test(vararg ts: String) = ts");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
Object[] args = {"mama", "papa"};
|
||||
assertTrue(args == main.invoke(null, args));
|
||||
*/
|
||||
String[] args = {"mama", "papa"};
|
||||
assertTrue(args == main.invoke(null, new Object[]{ args } ));
|
||||
}
|
||||
|
||||
public void testIntArray () throws InvocationTargetException, IllegalAccessException {
|
||||
/*
|
||||
loadText("fun test(vararg ts: Int) = ts");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
int[] args = {3, 4};
|
||||
assertTrue(args == main.invoke(null, args));
|
||||
*/
|
||||
assertTrue(args == main.invoke(null, new Object[]{ args }));
|
||||
}
|
||||
|
||||
public void testIntArrayKotlinNoArgs () throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(); fun testf(vararg ts: Int) = ts");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
Object res = main.invoke(null, new Object[]{});
|
||||
assertTrue(((int[])res).length == 0);
|
||||
}
|
||||
|
||||
public void testIntArrayKotlin () throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(239, 7); fun testf(vararg ts: Int) = ts");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
Object res = main.invoke(null, new Object[]{});
|
||||
assertTrue(((int[])res).length == 2);
|
||||
assertTrue(((int[])res)[0] == 239);
|
||||
assertTrue(((int[])res)[1] == 7);
|
||||
}
|
||||
|
||||
public void testNullableIntArrayKotlin () throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(239.byt, 7.byt); fun testf(vararg ts: Byte?) = ts");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
Object res = main.invoke(null, new Object[]{});
|
||||
assertTrue(((Byte[])res).length == 2);
|
||||
assertTrue(((Byte[])res)[0] == (byte)239);
|
||||
assertTrue(((Byte[])res)[1] == 7);
|
||||
}
|
||||
|
||||
public void testIntArrayKotlinObj () throws InvocationTargetException, IllegalAccessException {
|
||||
loadText("fun test() = testf(\"239\"); fun testf(vararg ts: String) = ts");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
Object res = main.invoke(null, new Object[]{});
|
||||
assertTrue(((String[])res).length == 1);
|
||||
assertTrue(((String[])res)[0].equals("239"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture {
|
||||
List<JetDeclaration> declarations = file.getRootNamespace().getDeclarations();
|
||||
JetDeclaration aClass = declarations.get(0);
|
||||
assert aClass instanceof JetClass;
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
|
||||
DeclarationDescriptor classDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
|
||||
WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING);
|
||||
assert classDescriptor instanceof ClassifierDescriptor;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
Code Generation 2012 - Session Proposal Form
|
||||
|
||||
Submission Deadline: Friday December 9th 2011
|
||||
|
||||
Session title:
|
||||
|
||||
DSLs in Kotlin
|
||||
|
||||
Session type and duration:
|
||||
|
||||
Tutorial, 60 min
|
||||
|
||||
Session abstract:
|
||||
|
||||
Kotlin is a statically typed programming language for the JVM, proposed recently by JetBrains. The language is intended for industrial use as a safer and more convenient alternative to Java. The language is fully Java compatible, so one can mix Kotlin and Java sources in the same project. Language documentation is available at http://jetbrains.com/kotlin.
|
||||
|
||||
In this session we will demonstrate Kotlin's abilities to define APIs as domain-specific languages (DSLs). This includes explanation of interesting language features illustrated with practical use-cases.
|
||||
|
||||
As a flagship example we will present Type-safe Builders, a technique that improves upon Groovy builders (http://groovy.codehaus.org/Builders) by making them statically checked for correctness. This enables specifying declarative data right inside the code. Want to describe a build file? Xml/HTML? Swing UI? Use builders! We will show how Kotlin compiler itself uses builders to specify modules. Along with this example we will show and explain a few other DSLs built in Kotlin.
|
||||
|
||||
Benefits of participating:
|
||||
|
||||
Participants will learn about Kotlin and how a few language features can be combined to create internal DSLs in a natural and flexible way.
|
||||
|
||||
Process & timetable:
|
||||
|
||||
Introduction to Kotlin — 7-10 minutes
|
||||
Q&A - 5 minutes
|
||||
DSL-enabling features - 15 minutes
|
||||
Q&A - 5 minutes
|
||||
Builders (live demo) - 20 minutes
|
||||
Q&A - 5 minutes
|
||||
|
||||
Session outputs:
|
||||
|
||||
Slides, example code
|
||||
|
||||
Intended Audience:
|
||||
|
||||
The session is intended for developers and tech leads.
|
||||
We expect the audience to be familiar with basic concepts of OOP and some of the statically typed languages (Java, Scala, C#, C++ etc).
|
||||
|
||||
Availability:
|
||||
|
||||
No constraints
|
||||
|
||||
Detailed Description / Supporting Information
|
||||
|
||||
Kotlin is a new statically typed JVM-targeted programming language developed by JetBrains and intended for industrial use. Kotlin is designed to be fully Java compatible, and at the same time safer, more concise than Java and way simpler than its main competitor, Scala. Also, IDE support is being developed in parallel with the language itself.
|
||||
|
||||
This session focuses on the language features that enable DSL creation and corresponding patterns.
|
||||
|
||||
During the introduction, we will give an overview of the language. The features we’re planning to cover include:
|
||||
* function literals (closures);
|
||||
* extension functions;
|
||||
* type inference;
|
||||
* operator overloading/overriding;
|
||||
* null safety and automatic casts.
|
||||
|
||||
As a flagship example we will present type-safe builders, a technique that improves upon Groovy builders (http://groovy.codehaus.org/Builders) by making them statically checked for correctness. Builders are a flexible and clean way of describing declarative data in the code with very little syntactic overhead. The technique is so handy that Kotlin uses it instead of XML for compiler configuration, which we will show in action along with XML/HTML and Swing UI building.
|
||||
This part is presented as a live demo within the IntelliJ IDEA IDE for Kotlin. Along with this example we'll demonstrate a DSL for LINQ-like collection processing and how to turn any type into a Fluent interface (http://martinfowler.com/bliki/FluentInterface.html) with extension functions.
|
||||
|
||||
This session has not been run before, but the material we use is partly taken from Kotlin talks from OSCON, StrangeLoop and Devoxx.
|
||||
|
||||
Main presenter name, contact details and biography
|
||||
|
||||
Name: Andrey Breslav
|
||||
Affiliation: JetBrains
|
||||
Telephone / Skype: andrey.breslav @ skype
|
||||
Email: andrey.breslav@jetbrains.com
|
||||
Biography (up to 100 words):
|
||||
Andrey is the lead language designer working on Project Kotlin. He joined JetBrains in 2010.
|
||||
@@ -0,0 +1,7 @@
|
||||
import kotlin.modules.ModuleSetBuilder
|
||||
|
||||
fun defineModules(builder: ModuleSetBuilder) {
|
||||
builder.module("hello") {
|
||||
source files "HelloNames.kt"
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="stdlib" />
|
||||
<orderEntry type="module" module-name="cli" />
|
||||
<orderEntry type="module" module-name="compiler-tests" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
/**
|
||||
@@ -26,7 +26,7 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider
|
||||
ref = PsiTreeUtil.getParentOfType(originalElement, JetReferenceExpression.class);
|
||||
}
|
||||
if (ref != null) {
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) element.getContainingFile());
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) element.getContainingFile());
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, ref);
|
||||
if (declarationDescriptor != null) {
|
||||
return render(declarationDescriptor);
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.jet.checkers.CheckerTestUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
@@ -28,7 +29,7 @@ public class CopyAsDiagnosticTestAction extends AnAction {
|
||||
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
|
||||
assert editor != null && psiFile != null;
|
||||
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) psiFile);
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile);
|
||||
|
||||
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -26,7 +26,7 @@ public class ShowExpressionTypeAction extends AnAction {
|
||||
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
|
||||
assert editor != null && psiFile != null;
|
||||
JetExpression expression;
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) psiFile);
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile);
|
||||
if (editor.getSelectionModel().hasSelection()) {
|
||||
int startOffset = editor.getSelectionModel().getSelectionStart();
|
||||
int endOffset = editor.getSelectionModel().getSelectionEnd();
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.JetHighlighter;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
@@ -53,7 +54,7 @@ public class DebugInfoAnnotator implements Annotator {
|
||||
if (element instanceof JetFile) {
|
||||
JetFile file = (JetFile) element;
|
||||
try {
|
||||
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
|
||||
final Set<JetReferenceExpression> unresolvedReferences = Sets.newHashSet();
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -45,7 +45,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
JetFile file = PsiTreeUtil.getParentOfType(element, JetFile.class);
|
||||
|
||||
if (file == null) return null;
|
||||
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
|
||||
if (element instanceof JetClass) {
|
||||
JetClass jetClass = (JetClass) element;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.plugin.JetHighlighter;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.quickfix.JetIntentionActionFactory;
|
||||
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
|
||||
|
||||
@@ -54,12 +55,13 @@ public class JetPsiChecker implements Annotator {
|
||||
JetFile file = (JetFile) element;
|
||||
Project project = element.getProject();
|
||||
try {
|
||||
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
|
||||
if (errorReportingEnabled) {
|
||||
Collection<Diagnostic> diagnostics = Sets.newLinkedHashSet(bindingContext.getDiagnostics());
|
||||
Set<PsiElement> redeclarations = Sets.newHashSet();
|
||||
for (Diagnostic diagnostic : diagnostics) {
|
||||
if (diagnostic.getFactory().getPsiFile(diagnostic) != file) continue; // This is needed because we have the same context for all files
|
||||
Annotation annotation = null;
|
||||
if (diagnostic.getSeverity() == Severity.ERROR) {
|
||||
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jet.plugin.compiler;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
@@ -66,16 +67,21 @@ public class JetCompiler implements TranslatingCompiler {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
VirtualFile[] allFiles = compileContext.getCompileScope().getFiles(null, true);
|
||||
|
||||
GenerationState generationState = new GenerationState(compileContext.getProject(), false);
|
||||
List<JetNamespace> namespaces = Lists.newArrayList();
|
||||
for (VirtualFile virtualFile : virtualFiles) {
|
||||
for (VirtualFile virtualFile : allFiles) {
|
||||
PsiFile psiFile = PsiManager.getInstance(compileContext.getProject()).findFile(virtualFile);
|
||||
if (psiFile instanceof JetFile) {
|
||||
namespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
}
|
||||
}
|
||||
|
||||
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(compileContext.getProject(), namespaces, JetControlFlowDataTraceFactory.EMPTY);
|
||||
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(
|
||||
compileContext.getProject(), namespaces,
|
||||
Predicates.<PsiFile>alwaysTrue(),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
|
||||
boolean errors = false;
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.jetbrains.jet.plugin.compiler;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.JetFileType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class WholeProjectAnalyzerFacade {
|
||||
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
|
||||
@Override
|
||||
public Collection<JetDeclaration> fun(final JetFile rootFile) {
|
||||
final Project project = rootFile.getProject();
|
||||
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
|
||||
ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
|
||||
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
VirtualFile[] contentRoots = rootManager.getContentRoots();
|
||||
|
||||
CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() {
|
||||
@Override
|
||||
protected void acceptFile(VirtualFile file, String fileRoot, String filePath) {
|
||||
final FileType fileType = FileTypeManager.getInstance().getFileTypeByFile(file);
|
||||
if (fileType != JetFileType.INSTANCE) return;
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (psiFile instanceof JetFile) {
|
||||
if (rootFile.getOriginalFile() != psiFile) {
|
||||
namespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
namespaces.add(rootFile.getRootNamespace());
|
||||
return namespaces;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
|
||||
return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,8 +21,8 @@ import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -125,7 +125,7 @@ public class JetPositionManager implements PositionManager {
|
||||
if (mapper != null) {
|
||||
return mapper;
|
||||
}
|
||||
final BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(myDebugProcess.getProject());
|
||||
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
file.acceptChildren(new JetVisitorVoid() {
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -76,7 +76,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
|
||||
protected PsiElement doResolve() {
|
||||
JetFile file = (JetFile) getElement().getContainingFile();
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, myExpression);
|
||||
if (psiElement != null) {
|
||||
return psiElement;
|
||||
@@ -88,7 +88,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
JetFile file = (JetFile) getElement().getContainingFile();
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
Collection<? extends ResolvedCallImpl<? extends DeclarationDescriptor>> resolvedCalls = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (resolvedCalls == null) return ResolveResult.EMPTY_ARRAY;
|
||||
ResolveResult[] results = new ResolveResult[resolvedCalls.size()];
|
||||
|
||||
@@ -13,9 +13,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.List;
|
||||
@@ -51,7 +51,7 @@ class JetSimpleNameReference extends JetPsiReference {
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
|
||||
JetExpression receiverExpression = qualifiedExpression.getReceiverExpression();
|
||||
JetFile file = (JetFile) myExpression.getContainingFile();
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
final JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
|
||||
if (expressionType != null) {
|
||||
return collectLookupElements(bindingContext, expressionType.getMemberScope());
|
||||
@@ -59,7 +59,7 @@ class JetSimpleNameReference extends JetPsiReference {
|
||||
}
|
||||
else {
|
||||
JetFile file = (JetFile) myExpression.getContainingFile();
|
||||
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
JetScope resolutionScope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, myExpression);
|
||||
if (resolutionScope != null) {
|
||||
return collectLookupElements(bindingContext, resolutionScope);
|
||||
|
||||
@@ -8,9 +8,12 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.List;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.plugin.JetMainDetector;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -22,6 +25,17 @@ public class JetRunConfigurationProducer extends RuntimeConfigurationProducer im
|
||||
super(JetRunConfigurationType.getInstance());
|
||||
}
|
||||
|
||||
private static String getFQName(JetClass jetClass) {
|
||||
JetNamedDeclaration parent = PsiTreeUtil.getParentOfType(jetClass, JetNamespace.class, JetClass.class);
|
||||
if (parent instanceof JetNamespace) {
|
||||
return ((JetNamespace) parent).getFQName() + "." + jetClass.getName();
|
||||
}
|
||||
if (parent instanceof JetClass) {
|
||||
return getFQName(((JetClass) parent)) + "." + jetClass.getName();
|
||||
}
|
||||
return jetClass.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getSourceElement() {
|
||||
return mySourceElement;
|
||||
@@ -30,14 +44,14 @@ public class JetRunConfigurationProducer extends RuntimeConfigurationProducer im
|
||||
@Override
|
||||
protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext configurationContext) {
|
||||
JetClass containingClass = (JetClass) location.getParentElement(JetClass.class);
|
||||
if (containingClass != null && hasMain(containingClass.getDeclarations())) {
|
||||
if (containingClass != null && JetMainDetector.hasMain(containingClass.getDeclarations())) {
|
||||
mySourceElement = containingClass;
|
||||
return createConfigurationByQName(location.getModule(), configurationContext, containingClass.getFQName());
|
||||
return createConfigurationByQName(location.getModule(), configurationContext, getFQName(containingClass));
|
||||
}
|
||||
PsiFile psiFile = location.getPsiElement().getContainingFile();
|
||||
if (psiFile instanceof JetFile) {
|
||||
JetNamespace namespace = ((JetFile) psiFile).getRootNamespace();
|
||||
if (hasMain(namespace.getDeclarations())) {
|
||||
if (JetMainDetector.hasMain(namespace.getDeclarations())) {
|
||||
mySourceElement = namespace;
|
||||
return createConfigurationByQName(location.getModule(), configurationContext, namespace.getFQName() + ".namespace");
|
||||
}
|
||||
@@ -45,25 +59,6 @@ public class JetRunConfigurationProducer extends RuntimeConfigurationProducer im
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasMain(List<JetDeclaration> declarations) {
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction) declaration;
|
||||
if ("main".equals(function.getName())) {
|
||||
List<JetParameter> parameters = function.getValueParameters();
|
||||
if (parameters.size() == 1) {
|
||||
JetTypeReference reference = parameters.get(0).getTypeReference();
|
||||
if (reference != null && reference.getText().equals("Array<String>")) { // TODO correct check
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private RunnerAndConfigurationSettings createConfigurationByQName(Module module, ConfigurationContext context, String fqName) {
|
||||
RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(module.getProject(), context);
|
||||
JetRunConfiguration configuration = (JetRunConfiguration) settings.getConfiguration();
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
namespace kotlin.modules
|
||||
namespace kotlin
|
||||
|
||||
namespace modules {
|
||||
|
||||
import java.util.*
|
||||
import jet.modules.*
|
||||
|
||||
class ModuleSetBuilder() {
|
||||
val modules: ArrayList<ModuleBuilder> = ArrayList<ModuleBuilder>()
|
||||
class ModuleSetBuilder(): IModuleSetBuilder {
|
||||
val modules: ArrayList<IModuleBuilder?> = ArrayList<IModuleBuilder?>()
|
||||
|
||||
fun module(name: String, callback: fun ModuleBuilder.()) {
|
||||
val builder = ModuleBuilder(name)
|
||||
builder.callback()
|
||||
modules.add(builder)
|
||||
}
|
||||
|
||||
override fun getModules(): List<IModuleBuilder?>? = modules
|
||||
}
|
||||
|
||||
class SourcesBuilder(val parent: ModuleBuilder) {
|
||||
@@ -44,4 +49,7 @@ class ModuleBuilder(val name: String): IModuleBuilder {
|
||||
|
||||
override fun getSourceFiles(): List<String?>? = sourceFiles
|
||||
override fun getClasspathRoots(): List<String?>? = classpathRoots
|
||||
override fun getModuleName(): String? = name
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public interface IModuleBuilder {
|
||||
String getModuleName();
|
||||
List<String> getSourceFiles();
|
||||
List<String> getClasspathRoots();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package jet.modules;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface IModuleSetBuilder {
|
||||
List<IModuleBuilder> getModules();
|
||||
}
|
||||
Reference in New Issue
Block a user