namespace-level functions supported + tests for resolve to Java
This commit is contained in:
@@ -9,7 +9,8 @@ import com.intellij.util.IncorrectOperationException;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.ErrorHandler;
|
import org.jetbrains.jet.lang.ErrorHandler;
|
||||||
import org.jetbrains.jet.lang.resolve.*;
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +29,11 @@ public class JetReferenceExpression extends JetExpression {
|
|||||||
return node == null ? null : node.getText();
|
return node == null ? null : node.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable @IfNotParsed
|
||||||
|
public PsiElement getReferencedNameElement() {
|
||||||
|
return findChildByType(REFERENCE_TOKENS);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(JetVisitor visitor) {
|
public void accept(JetVisitor visitor) {
|
||||||
visitor.visitReferenceExpression(this);
|
visitor.visitReferenceExpression(this);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class AnalyzingUtils {
|
|||||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||||
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext);
|
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext);
|
||||||
|
|
||||||
ScopeWithImports scope = new ScopeWithImports(semanticServices.getStandardLibrary().getLibraryScope());
|
WritableScope scope = new WritableScope(semanticServices.getStandardLibrary().getLibraryScope());
|
||||||
scope.importScope(new JavaPackageScope("", javaSemanticServices));
|
scope.importScope(new JavaPackageScope("", javaSemanticServices));
|
||||||
scope.importScope(new JavaPackageScope("java.lang", javaSemanticServices));
|
scope.importScope(new JavaPackageScope("java.lang", javaSemanticServices));
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class ClassDescriptorResolver {
|
|||||||
JetExpression bodyExpression = function.getBodyExpression();
|
JetExpression bodyExpression = function.getBodyExpression();
|
||||||
assert bodyExpression != null : "No type, no body"; // TODO
|
assert bodyExpression != null : "No type, no body"; // TODO
|
||||||
// TODO : Recursion possible
|
// TODO : Recursion possible
|
||||||
returnType = semanticServices.getTypeInferrer().getType(parameterScope, bodyExpression, function.hasBlockBody());
|
returnType = semanticServices.getTypeInferrer().safeGetType(parameterScope, bodyExpression, function.hasBlockBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
|
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.types.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author abreslav
|
|
||||||
*/
|
|
||||||
public class ScopeWithImports implements JetScope {
|
|
||||||
|
|
||||||
private final List<JetScope> imports = new ArrayList<JetScope>();
|
|
||||||
private final JetScope scope;
|
|
||||||
|
|
||||||
public ScopeWithImports(JetScope scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void importScope(JetScope imported) {
|
|
||||||
imports.add(0, imported);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassDescriptor getClass(@NotNull String name) {
|
|
||||||
ClassDescriptor descriptor = scope.getClass(name);
|
|
||||||
if (descriptor != null) return descriptor;
|
|
||||||
for (JetScope imported : imports) {
|
|
||||||
ClassDescriptor importedClass = imported.getClass(name);
|
|
||||||
if (importedClass != null) {
|
|
||||||
return importedClass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PropertyDescriptor getProperty(@NotNull String name) {
|
|
||||||
PropertyDescriptor descriptor = scope.getProperty(name);
|
|
||||||
if (descriptor != null) return descriptor;
|
|
||||||
for (JetScope imported : imports) {
|
|
||||||
PropertyDescriptor importedDescriptor = imported.getProperty(name);
|
|
||||||
if (importedDescriptor != null) {
|
|
||||||
return importedDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ExtensionDescriptor getExtension(@NotNull String name) {
|
|
||||||
throw new UnsupportedOperationException(); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NamespaceDescriptor getNamespace(@NotNull String name) {
|
|
||||||
NamespaceDescriptor descriptor = scope.getNamespace(name);
|
|
||||||
if (descriptor != null) return descriptor;
|
|
||||||
for (JetScope imported : imports) {
|
|
||||||
NamespaceDescriptor importedDescriptor = imported.getNamespace(name);
|
|
||||||
if (importedDescriptor != null) {
|
|
||||||
return importedDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeParameterDescriptor getTypeParameter(@NotNull String name) {
|
|
||||||
return scope.getTypeParameter(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Type getThisType() {
|
|
||||||
return scope.getThisType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
|
||||||
return scope.getFunctionGroup(name); // TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,7 @@ import java.util.*;
|
|||||||
public class TopDownAnalyzer {
|
public class TopDownAnalyzer {
|
||||||
|
|
||||||
private final Map<JetClass, MutableClassDescriptor> classes = new LinkedHashMap<JetClass, MutableClassDescriptor>();
|
private final Map<JetClass, MutableClassDescriptor> classes = new LinkedHashMap<JetClass, MutableClassDescriptor>();
|
||||||
|
private final Map<JetNamespace, WritableScope> namespaceScopes = new LinkedHashMap<JetNamespace, WritableScope>();
|
||||||
private final Map<JetFunction, FunctionDescriptor> functions = new HashMap<JetFunction, FunctionDescriptor>();
|
private final Map<JetFunction, FunctionDescriptor> functions = new HashMap<JetFunction, FunctionDescriptor>();
|
||||||
private final Map<JetDeclaration, WritableScope> declaringScopes = new HashMap<JetDeclaration, WritableScope>();
|
private final Map<JetDeclaration, WritableScope> declaringScopes = new HashMap<JetDeclaration, WritableScope>();
|
||||||
|
|
||||||
@@ -56,7 +57,8 @@ public class TopDownAnalyzer {
|
|||||||
public void visitNamespace(JetNamespace namespace) {
|
public void visitNamespace(JetNamespace namespace) {
|
||||||
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
|
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
|
||||||
|
|
||||||
ScopeWithImports scopeWithImports = new ScopeWithImports(declaringScope);
|
WritableScope namespaceScope = new WritableScope(declaringScope);
|
||||||
|
namespaceScopes.put(namespace, namespaceScope);
|
||||||
|
|
||||||
for (JetImportDirective importDirective : importDirectives) {
|
for (JetImportDirective importDirective : importDirectives) {
|
||||||
if (importDirective.isAbsoluteInRootNamespace()) {
|
if (importDirective.isAbsoluteInRootNamespace()) {
|
||||||
@@ -64,15 +66,15 @@ public class TopDownAnalyzer {
|
|||||||
}
|
}
|
||||||
if (importDirective.isAllUnder()) {
|
if (importDirective.isAllUnder()) {
|
||||||
JetExpression importedReference = importDirective.getImportedReference();
|
JetExpression importedReference = importDirective.getImportedReference();
|
||||||
Type type = semanticServices.getTypeInferrer(trace).getType(scopeWithImports, importedReference, false);
|
Type type = semanticServices.getTypeInferrer(trace).getType(namespaceScope, importedReference, false);
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
scopeWithImports.importScope(type.getMemberScope());
|
namespaceScope.importScope(type.getMemberScope());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WritableScope namespaceScope = new WritableScope(scopeWithImports);
|
|
||||||
collectTypeDeclarators(namespaceScope, namespace.getDeclarations());
|
collectTypeDeclarators(namespaceScope, namespace.getDeclarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +140,8 @@ public class TopDownAnalyzer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNamespace(JetNamespace namespace) {
|
public void visitNamespace(JetNamespace namespace) {
|
||||||
collectBehaviorDeclarators(declaringScope, namespace.getDeclarations());
|
WritableScope namespaceScope = namespaceScopes.get(namespace);
|
||||||
|
collectBehaviorDeclarators(namespaceScope, namespace.getDeclarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -180,7 +180,11 @@ public class TypeResolver {
|
|||||||
return classDescriptor.getMemberScope(resolveTypeProjections(scope, classDescriptor.getTypeConstructor(), userType.getTypeArguments()));
|
return classDescriptor.getMemberScope(resolveTypeProjections(scope, classDescriptor.getTypeConstructor(), userType.getTypeArguments()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveNamespace(scope, userType).getMemberScope();
|
NamespaceDescriptor namespaceDescriptor = resolveNamespace(scope, userType);
|
||||||
|
if (namespaceDescriptor == null) {
|
||||||
|
return JetScope.EMPTY;
|
||||||
|
}
|
||||||
|
return namespaceDescriptor.getMemberScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -199,7 +203,9 @@ public class TypeResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NamespaceDescriptor namespace = scope.getNamespace(userType.getReferencedName());
|
NamespaceDescriptor namespace = scope.getNamespace(userType.getReferencedName());
|
||||||
trace.recordReferenceResolution(userType.getReferenceExpression(), namespace);
|
if (namespace != null) {
|
||||||
|
trace.recordReferenceResolution(userType.getReferenceExpression(), namespace);
|
||||||
|
}
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,11 +23,25 @@ public class WritableScope extends JetScopeAdapter {
|
|||||||
private Map<String, ClassDescriptor> classDescriptors;
|
private Map<String, ClassDescriptor> classDescriptors;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Type thisType;
|
private Type thisType;
|
||||||
|
@Nullable
|
||||||
|
private List<JetScope> imports;
|
||||||
|
|
||||||
public WritableScope(JetScope scope) {
|
public WritableScope(JetScope scope) {
|
||||||
super(scope);
|
super(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void importScope(JetScope imported) {
|
||||||
|
getImports().add(0, imported);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private List<JetScope> getImports() {
|
||||||
|
if (imports == null) {
|
||||||
|
imports = new ArrayList<JetScope>();
|
||||||
|
}
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Map<String, PropertyDescriptor> getPropertyDescriptors() {
|
private Map<String, PropertyDescriptor> getPropertyDescriptors() {
|
||||||
if (propertyDescriptors == null) {
|
if (propertyDescriptors == null) {
|
||||||
@@ -50,7 +66,17 @@ public class WritableScope extends JetScopeAdapter {
|
|||||||
if (propertyDescriptor != null) {
|
if (propertyDescriptor != null) {
|
||||||
return propertyDescriptor;
|
return propertyDescriptor;
|
||||||
}
|
}
|
||||||
return super.getProperty(name);
|
propertyDescriptor = super.getProperty(name);
|
||||||
|
if (propertyDescriptor != null) {
|
||||||
|
return propertyDescriptor;
|
||||||
|
}
|
||||||
|
for (JetScope imported : getImports()) {
|
||||||
|
PropertyDescriptor importedDescriptor = imported.getProperty(name);
|
||||||
|
if (importedDescriptor != null) {
|
||||||
|
return importedDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -77,11 +103,20 @@ public class WritableScope extends JetScopeAdapter {
|
|||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||||
WritableFunctionGroup functionGroup = getFunctionGroups().get(name);
|
FunctionGroup functionGroup = getFunctionGroups().get(name);
|
||||||
if (functionGroup != null && !functionGroup.isEmpty()) {
|
if (functionGroup != null && !functionGroup.isEmpty()) {
|
||||||
return functionGroup;
|
return functionGroup;
|
||||||
}
|
}
|
||||||
return super.getFunctionGroup(name);
|
// TODO : this logic is questionable
|
||||||
|
functionGroup = super.getFunctionGroup(name);
|
||||||
|
if (!functionGroup.isEmpty()) return functionGroup;
|
||||||
|
for (JetScope imported : getImports()) {
|
||||||
|
FunctionGroup importedDescriptor = imported.getFunctionGroup(name);
|
||||||
|
if (!importedDescriptor.isEmpty()) {
|
||||||
|
return importedDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return functionGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -132,10 +167,17 @@ public class WritableScope extends JetScopeAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public ClassDescriptor getClass(@NotNull String name) {
|
public ClassDescriptor getClass(@NotNull String name) {
|
||||||
ClassDescriptor classDescriptor = getClassDescriptors().get(name);
|
ClassDescriptor classDescriptor = getClassDescriptors().get(name);
|
||||||
if (classDescriptor != null) {
|
if (classDescriptor != null) return classDescriptor;
|
||||||
return classDescriptor;
|
|
||||||
|
classDescriptor = super.getClass(name);
|
||||||
|
if (classDescriptor != null) return classDescriptor;
|
||||||
|
for (JetScope imported : getImports()) {
|
||||||
|
ClassDescriptor importedClass = imported.getClass(name);
|
||||||
|
if (importedClass != null) {
|
||||||
|
return importedClass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.getClass(name);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -149,7 +191,15 @@ public class WritableScope extends JetScopeAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamespaceDescriptor getNamespace(@NotNull String name) {
|
public NamespaceDescriptor getNamespace(@NotNull String name) {
|
||||||
return super.getNamespace(name); // TODO
|
NamespaceDescriptor namespace = super.getNamespace(name);
|
||||||
|
if (namespace != null) return namespace;
|
||||||
|
for (JetScope imported : getImports()) {
|
||||||
|
NamespaceDescriptor importedDescriptor = imported.getNamespace(name);
|
||||||
|
if (importedDescriptor != null) {
|
||||||
|
return importedDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -28,20 +28,16 @@ public class JetTypeInferrer {
|
|||||||
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, trace);
|
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@NotNull
|
||||||
: "new" constructorInvocation
|
public Type safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
|
||||||
|
Type type = getType(scope, expression, preferBlock);
|
||||||
|
if (type != null) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
return ErrorType.createErrorType("Type for " + expression.getText());
|
||||||
|
}
|
||||||
|
|
||||||
: objectLiteral
|
@Nullable
|
||||||
|
|
||||||
: SimpleName
|
|
||||||
|
|
||||||
: "typeof" "(" expression ")"
|
|
||||||
|
|
||||||
: functionLiteral
|
|
||||||
|
|
||||||
: declaration
|
|
||||||
: "namespace" // for the root namespace
|
|
||||||
*/
|
|
||||||
public Type getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
|
public Type getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
|
||||||
final Type[] result = new Type[1];
|
final Type[] result = new Type[1];
|
||||||
expression.accept(new JetVisitor() {
|
expression.accept(new JetVisitor() {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import `java::java`java.*
|
||||||
|
import `java::java.util`util.*
|
||||||
|
|
||||||
|
fun foo(o : `java::java.lang.Object`Object, l : `java::java.util`util.`java::java.util.List`List) : `java::java.util.List`List {}
|
||||||
|
|
||||||
|
~A~class A {
|
||||||
|
fun f(a : `java::java.util`util.`java::java.util.List`List) {}
|
||||||
|
fun f(a : `java::java.util.List`List) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : `java::java.lang.Object`Object {
|
||||||
|
fun bar(~o~o : `java::java.lang.Object`Object) {
|
||||||
|
`java::java.lang.System`System.`java::java.lang.System.out`out.`java::java.io.PrintStream.print(Object)`print(`o`o)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f(a : `java::java.util`util.`java::java.util.List`List) {}
|
||||||
|
fun f(a : `java::java.util.List`List) {}
|
||||||
|
|
||||||
|
|
||||||
|
~foo~fun foo(abc : `A`A) : `A`A {
|
||||||
|
`java::java`java.`java::java.lang`lang.`java::java.lang.System`System.`java::java.lang.System.out`out.`java::java.io.PrintStream.print(Int)`print(1)
|
||||||
|
`java::java.util`util.`java::java.util.Collections`Collections.`java::java.util.Collections.emptyList()`emptyList()
|
||||||
|
`java::java`java.`!`Foo
|
||||||
|
`java::java.util.Collections`Collections.`java::java.util.Collections.emptyList()`emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun barrr() : `std::Int`Int {
|
||||||
|
`foo`foo(new `A`A())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,15 +10,11 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertNotNull;
|
import static junit.framework.Assert.*;
|
||||||
import static junit.framework.Assert.assertSame;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -28,16 +24,24 @@ public class ExpectedResolveData {
|
|||||||
private final Map<String, Integer> declarationToPosition = new HashMap<String, Integer>();
|
private final Map<String, Integer> declarationToPosition = new HashMap<String, Integer>();
|
||||||
private final Map<Integer, String> positionToReference = new HashMap<Integer, String>();
|
private final Map<Integer, String> positionToReference = new HashMap<Integer, String>();
|
||||||
private final Map<Integer, String> positionToType = new HashMap<Integer, String>();
|
private final Map<Integer, String> positionToType = new HashMap<Integer, String>();
|
||||||
|
private final Map<String, DeclarationDescriptor> nameToDescriptor;
|
||||||
|
private final Map<String, PsiElement> nameToPsiElement;
|
||||||
|
|
||||||
public ExpectedResolveData(final Document document) {
|
|
||||||
|
public ExpectedResolveData(Map<String, DeclarationDescriptor> nameToDescriptor, Map<String, PsiElement> nameToPsiElement) {
|
||||||
|
this.nameToDescriptor = nameToDescriptor;
|
||||||
|
this.nameToPsiElement = nameToPsiElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void extractData(final Document document) {
|
||||||
new WriteCommandAction.Simple(null) {
|
new WriteCommandAction.Simple(null) {
|
||||||
public void run() {
|
public void run() {
|
||||||
extractData(document);
|
doExtractData(document);
|
||||||
}
|
}
|
||||||
}.execute().throwException();
|
}.execute().throwException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractData(Document document) {
|
private void doExtractData(Document document) {
|
||||||
String text = document.getText();
|
String text = document.getText();
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile("(~[^~]+~)|(`[^`]+`)");
|
Pattern pattern = Pattern.compile("(~[^~]+~)|(`[^`]+`)");
|
||||||
@@ -71,12 +75,16 @@ public class ExpectedResolveData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void checkResult(JetFile file) {
|
public void checkResult(JetFile file) {
|
||||||
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(file.getProject(), ErrorHandler.THROW_EXCEPTION);
|
final Set<PsiElement> unresolvedReferences = new HashSet<PsiElement>();
|
||||||
|
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(file.getProject(), new ErrorHandler() {
|
||||||
|
@Override
|
||||||
|
public void unresolvedReference(JetReferenceExpression referenceExpression) {
|
||||||
|
unresolvedReferences.add(referenceExpression.getReferencedNameElement());
|
||||||
|
}
|
||||||
|
});
|
||||||
JetStandardLibrary lib = semanticServices.getStandardLibrary();
|
JetStandardLibrary lib = semanticServices.getStandardLibrary();
|
||||||
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
|
|
||||||
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
|
|
||||||
|
|
||||||
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, ErrorHandler.THROW_EXCEPTION);
|
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, semanticServices.getErrorHandler());
|
||||||
|
|
||||||
Map<String, JetDeclaration> nameToDeclaration = new HashMap<String, JetDeclaration>();
|
Map<String, JetDeclaration> nameToDeclaration = new HashMap<String, JetDeclaration>();
|
||||||
|
|
||||||
@@ -96,7 +104,15 @@ public class ExpectedResolveData {
|
|||||||
String name = entry.getValue();
|
String name = entry.getValue();
|
||||||
PsiElement element = file.findElementAt(position);
|
PsiElement element = file.findElementAt(position);
|
||||||
|
|
||||||
JetDeclaration expected = nameToDeclaration.get(name);
|
if ("!".equals(name)) {
|
||||||
|
assertTrue("Must have been unresolved: " + element, unresolvedReferences.contains(element));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PsiElement expected = nameToDeclaration.get(name);
|
||||||
|
if (expected == null) {
|
||||||
|
expected = nameToPsiElement.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
JetReferenceExpression reference = getAncestorOfType(JetReferenceExpression.class, element);
|
JetReferenceExpression reference = getAncestorOfType(JetReferenceExpression.class, element);
|
||||||
if (expected == null && name.startsWith("std::")) {
|
if (expected == null && name.startsWith("std::")) {
|
||||||
@@ -158,17 +174,6 @@ public class ExpectedResolveData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DeclarationDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) {
|
|
||||||
FunctionGroup functionGroup = classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()).getFunctionGroup(name);
|
|
||||||
Collection<FunctionDescriptor> functions = functionGroup.getPossiblyApplicableFunctions(Collections.<Type>emptyList(), Collections.singletonList(parameterType));
|
|
||||||
for (FunctionDescriptor function : functions) {
|
|
||||||
if (function.getUnsubstitutedValueParameters().get(0).getType().equals(parameterType)) {
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterType + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T getAncestorOfType(Class<T> type, PsiElement element) {
|
private <T> T getAncestorOfType(Class<T> type, PsiElement element) {
|
||||||
while (element != null && !type.isInstance(element)) {
|
while (element != null && !type.isInstance(element)) {
|
||||||
element = element.getParent();
|
element = element.getParent();
|
||||||
|
|||||||
@@ -28,17 +28,21 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase {
|
public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase {
|
||||||
private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
|
private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
|
||||||
|
private ExpectedResolveData expectedResolveData;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
expectedResolveData = getExpectedResolveData();
|
||||||
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).prepareForTest(true);
|
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).prepareForTest(true);
|
||||||
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
|
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract ExpectedResolveData getExpectedResolveData();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(true); // has to cleanup by hand since light project does not get disposed any time soon
|
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(); // has to cleanup by hand since light project does not get disposed any time soon
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +73,7 @@ public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase
|
|||||||
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
|
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
|
||||||
|
|
||||||
// ExpectedHighlightingData expectedData = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos);
|
// ExpectedHighlightingData expectedData = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos);
|
||||||
ExpectedResolveData expectedData = new ExpectedResolveData(getEditor().getDocument());
|
expectedResolveData.extractData(getEditor().getDocument());
|
||||||
|
|
||||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
getFile().getText(); //to load text
|
getFile().getText(); //to load text
|
||||||
@@ -80,7 +84,7 @@ public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase
|
|||||||
|
|
||||||
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
|
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
|
||||||
|
|
||||||
expectedData.checkResult((JetFile) getFile());
|
expectedResolveData.checkResult((JetFile) getFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
package org.jetbrains.jet.resolve;
|
package org.jetbrains.jet.resolve;
|
||||||
|
|
||||||
import com.intellij.openapi.application.PathManager;
|
import com.intellij.openapi.application.PathManager;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk;
|
||||||
|
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||||
|
import com.intellij.psi.JavaPsiFacade;
|
||||||
|
import com.intellij.psi.PsiClass;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiMethod;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -11,8 +23,55 @@ import java.io.File;
|
|||||||
public class JetResolveTest extends ExtensibleResolveTestCase {
|
public class JetResolveTest extends ExtensibleResolveTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUp() throws Exception {
|
protected ExpectedResolveData getExpectedResolveData() {
|
||||||
super.setUp();
|
Project project = getProject();
|
||||||
|
JetStandardLibrary lib = JetStandardLibrary.getJetStandardLibrary(project);
|
||||||
|
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
|
||||||
|
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
|
||||||
|
|
||||||
|
Map<String,PsiElement> nameToDeclaration = new HashMap<String, PsiElement>();
|
||||||
|
nameToDeclaration.put("java::java.util.Collections.emptyList()", findMethod(findClass(project, "java.util.Collections"), "emptyList"));
|
||||||
|
nameToDeclaration.put("java::java.util.Collections", findClass(project, "java.util.Collections"));
|
||||||
|
nameToDeclaration.put("java::java.util.List", findClass(project, "java.util.List"));
|
||||||
|
nameToDeclaration.put("java::java", findPackage(project, "java"));
|
||||||
|
nameToDeclaration.put("java::java.util", findPackage(project, "java.util"));
|
||||||
|
nameToDeclaration.put("java::java.lang", findPackage(project, "java.lang"));
|
||||||
|
nameToDeclaration.put("java::java.lang.Object", findClass(project, "java.lang.Object"));
|
||||||
|
nameToDeclaration.put("java::java.lang.System", findClass(project, "java.lang.System"));
|
||||||
|
PsiMethod[] methods = findClass(project, "java.io.PrintStream").findMethodsByName("print", true);
|
||||||
|
nameToDeclaration.put("java::java.io.PrintStream.print(Object)", methods[8]);
|
||||||
|
nameToDeclaration.put("java::java.io.PrintStream.print(Int)", methods[2]);
|
||||||
|
nameToDeclaration.put("java::java.lang.System.out", findClass(project, "java.lang.System").findFieldByName("out", true));
|
||||||
|
|
||||||
|
|
||||||
|
return new ExpectedResolveData(nameToDescriptor, nameToDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiElement findPackage(Project project, String qualifiedName) {
|
||||||
|
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(project);
|
||||||
|
return javaFacade.findPackage(qualifiedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiMethod findMethod(PsiClass collections, String name) {
|
||||||
|
PsiMethod[] emptyLists = collections.findMethodsByName(name, true);
|
||||||
|
return emptyLists[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsiClass findClass(Project project, String qualifiedName) {
|
||||||
|
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(project);
|
||||||
|
GlobalSearchScope javaSearchScope = GlobalSearchScope.allScope(project);
|
||||||
|
return javaFacade.findClass(qualifiedName, javaSearchScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeclarationDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) {
|
||||||
|
FunctionGroup functionGroup = classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()).getFunctionGroup(name);
|
||||||
|
Collection<FunctionDescriptor> functions = functionGroup.getPossiblyApplicableFunctions(Collections.<Type>emptyList(), Collections.singletonList(parameterType));
|
||||||
|
for (FunctionDescriptor function : functions) {
|
||||||
|
if (function.getUnsubstitutedValueParameters().get(0).getType().equals(parameterType)) {
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterType + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -20,6 +79,18 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
|||||||
return getHomeDirectory() + "/idea/testData";
|
return getHomeDirectory() + "/idea/testData";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Sdk getProjectJDK() {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
try {
|
||||||
|
properties.load(new FileReader(getHomeDirectory() + "/idea/idea.properties"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String home = properties.getProperty("idea.home");
|
||||||
|
return new JavaSdkImpl().createJdk("JDK", home + "/java/mockJDK-1.7/jre", true);
|
||||||
|
}
|
||||||
|
|
||||||
private static String getHomeDirectory() {
|
private static String getHomeDirectory() {
|
||||||
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
|
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
|
||||||
}
|
}
|
||||||
@@ -28,4 +99,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
|||||||
doTest("/resolve/Basic.jet", true, true);
|
doTest("/resolve/Basic.jet", true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testResolveToJava() throws Exception {
|
||||||
|
doTest("/resolve/ResolveToJava.jet", true, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user