Fully-qualified names of Java elements supported

This commit is contained in:
Andrey Breslav
2011-03-05 16:12:45 +03:00
parent da7f44b8f2
commit c40d0fce24
16 changed files with 150 additions and 79 deletions
@@ -2,19 +2,16 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.java.JavaLangScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import java.util.List;
/**
* @author max
*/
@@ -23,17 +20,10 @@ public class NamespaceCodegen {
}
public void generate(JetNamespace namespace, ClassVisitor v, Project project) {
List<JetDeclaration> declarations = namespace.getDeclarations();
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, ErrorHandler.THROW_EXCEPTION);
BindingTraceContext bindingTraceContext = new BindingTraceContext();
ScopeWithImports scope = new ScopeWithImports(semanticServices.getStandardLibrary().getLibraryScope());
scope.addImport(new JavaLangScope(new JavaSemanticServices(project, semanticServices, bindingTraceContext)));
new TopDownAnalyzer(semanticServices, bindingTraceContext).process(scope, declarations);
BindingContext bindingContext = bindingTraceContext;
BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, ErrorHandler.THROW_EXCEPTION);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v);
final FunctionCodegen functionCodegen = new FunctionCodegen(v, semanticServices.getStandardLibrary(), bindingContext);
final FunctionCodegen functionCodegen = new FunctionCodegen(v, JetStandardLibrary.getJetStandardLibrary(project), bindingContext);
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC,
getJVMClassName(namespace),
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang;
import com.intellij.lang.ASTNode;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
/**
@@ -12,8 +13,16 @@ public class ErrorHandler {
public void unresolvedReference(JetReferenceExpression referenceExpression) {
throw new IllegalStateException("Unresolved reference: " + referenceExpression.getReferencedName());
}
@Override
public void structuralError(ASTNode node, String errorMessage) {
throw new IllegalStateException(errorMessage);
}
};
public void unresolvedReference(JetReferenceExpression referenceExpression) {
}
public void structuralError(ASTNode node, String errorMessage) {
}
}
@@ -15,7 +15,7 @@ public class JetSemanticServices {
}
public static JetSemanticServices createSemanticServices(Project project, ErrorHandler errorHandler) {
return new JetSemanticServices(new JetStandardLibrary(project), errorHandler);
return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), errorHandler);
}
private final JetTypeInferrer typeInferrer;
@@ -7,14 +7,9 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.ScopeWithImports;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.java.JavaLangScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.types.Type;
/**
@@ -28,20 +23,13 @@ public class JetPsiChecker implements Annotator {
Project project = element.getProject();
JetFile file = (JetFile) element;
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(element.getProject(), new ErrorHandler() {
@Override
public void unresolvedReference(JetReferenceExpression referenceExpression) {
holder.createErrorAnnotation(referenceExpression, "Unresolved");
}
});
try {
ScopeWithImports scope = new ScopeWithImports(semanticServices.getStandardLibrary().getLibraryScope());
BindingTraceContext bindingTraceContext = new BindingTraceContext();
scope.addImport(new JavaLangScope(new JavaSemanticServices(project, semanticServices, bindingTraceContext)));
new TopDownAnalyzer(semanticServices, bindingTraceContext).process(
scope,
file.getRootNamespace().getDeclarations());
final BindingContext bindingContext = bindingTraceContext;
final BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, new ErrorHandler() {
@Override
public void unresolvedReference(JetReferenceExpression referenceExpression) {
holder.createErrorAnnotation(referenceExpression, "Unresolved");
}
});
file.getRootNamespace().accept(new JetVisitor() {
@Override
public void visitClass(JetClass klass) {
@@ -35,22 +35,30 @@ public class JetImportDirective extends JetElement {
}
@Nullable
public String getAliasName() {
private ASTNode getAliasNameNode() {
boolean asPassed = false;
ASTNode childNode = getNode().getFirstChildNode();
while (childNode != null) {
IElementType tt = childNode.getElementType();
if (tt == JetTokens.AS_KEYWORD) asPassed = true;
if (asPassed && tt == JetTokens.IDENTIFIER) {
return childNode.getText();
return childNode;
}
childNode = childNode.getTreeNext();
}
return null;
}
@Nullable
public String getAliasName() {
ASTNode aliasNameNode = getAliasNameNode();
if (aliasNameNode == null) {
return null;
}
return aliasNameNode.getText();
}
public boolean isAllUnder() {
return getNode().findChildByType(JetTokens.MAP) != null;
}
@@ -9,13 +9,7 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.ScopeWithImports;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.java.JavaLangScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lexer.JetTokens;
/**
@@ -71,15 +65,7 @@ public class JetReferenceExpression extends JetExpression {
element = element.getParent();
}
JetFile file = (JetFile) element;
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(element.getProject(), ErrorHandler.DO_NOTHING);
ScopeWithImports scope = new ScopeWithImports(semanticServices.getStandardLibrary().getLibraryScope());
BindingTraceContext bindingTraceContext = new BindingTraceContext();
scope.addImport(new JavaLangScope(new JavaSemanticServices(element.getProject(), semanticServices, bindingTraceContext)));
new TopDownAnalyzer(semanticServices, bindingTraceContext).process(scope, file.getRootNamespace().getDeclarations());
BindingContext bindingContext = bindingTraceContext;
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, ErrorHandler.DO_NOTHING);
return bindingContext.resolveToDeclarationPsiElement(JetReferenceExpression.this);
}
@@ -116,4 +102,5 @@ public class JetReferenceExpression extends JetExpression {
}
};
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.resolve;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
/**
* @author abreslav
*/
public class AnalyzingUtils {
public static BindingContext analyzeFile(@NotNull JetFile file, @NotNull ErrorHandler errorHandler) {
JetNamespace rootNamespace = file.getRootNamespace();
return analyzeNamespace(rootNamespace, errorHandler);
}
public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull ErrorHandler errorHandler) {
Project project = namespace.getProject();
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, errorHandler);
BindingTraceContext bindingTraceContext = new BindingTraceContext();
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext);
ScopeWithImports scope = new ScopeWithImports(semanticServices.getStandardLibrary().getLibraryScope());
scope.importScope(new JavaPackageScope("", javaSemanticServices));
scope.importScope(new JavaPackageScope("java.lang", javaSemanticServices));
new TopDownAnalyzer(semanticServices, bindingTraceContext).process(scope, namespace);
return bindingTraceContext;
}
}
@@ -18,7 +18,7 @@ public class ScopeWithImports implements JetScope {
this.scope = scope;
}
public void addImport(JetScope imported) {
public void importScope(JetScope imported) {
imports.add(0, imported);
}
@@ -68,18 +68,18 @@ public class ScopeWithImports implements JetScope {
@Override
public TypeParameterDescriptor getTypeParameter(@NotNull String name) {
throw new UnsupportedOperationException(); // TODO
return scope.getTypeParameter(name);
}
@NotNull
@Override
public Type getThisType() {
throw new UnsupportedOperationException(); // TODO
return scope.getThisType();
}
@NotNull
@Override
public FunctionGroup getFunctionGroup(@NotNull String name) {
throw new UnsupportedOperationException(); // TODO
return scope.getFunctionGroup(name); // TODO
}
}
@@ -34,7 +34,7 @@ public class ScopeWithReceiver extends JetScopeImpl {
@Override
public NamespaceDescriptor getNamespace(@NotNull String name) {
return outerScope.getNamespace(name);
return receiverTypeScope.getNamespace(name);
}
@Override
@@ -5,10 +5,7 @@ import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author abreslav
@@ -29,6 +26,10 @@ public class TopDownAnalyzer {
this.trace = bindingTrace;
}
public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) {
process(outerScope, Collections.singletonList(declaration));
}
public void process(@NotNull JetScope outerScope, @NotNull List<JetDeclaration> declarations) {
final WritableScope toplevelScope = new WritableScope(outerScope);
trace.setToplevelScope(toplevelScope); // TODO : this is a hack
@@ -51,6 +52,27 @@ public class TopDownAnalyzer {
collectTypeDeclarators(classScope, klass.getDeclarations());
}
@Override
public void visitNamespace(JetNamespace namespace) {
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
ScopeWithImports scopeWithImports = new ScopeWithImports(declaringScope);
for (JetImportDirective importDirective : importDirectives) {
// if (importDirective.isAllUnder()) {
// // TODO: this works only for Java,
// // but should thoroughly resolve qualified names item-by-item
// // taking previous imports into account
// String importedName = importDirective.getImportedName();
// scopeWithImports.importScope(new JavaPackageScope(importedName, ));
// } else {
// throw new UnsupportedOperationException();
// }
}
WritableScope namespaceScope = new WritableScope(scopeWithImports);
collectTypeDeclarators(namespaceScope, namespace.getDeclarations());
}
@Override
public void visitTypedef(JetTypedef typedef) {
processTypeDef(typedef);
@@ -67,10 +89,13 @@ public class TopDownAnalyzer {
private WritableScope processClass(@NotNull WritableScope declaringScope, JetClass klass) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(declaringScope);
mutableClassDescriptor.setName(klass.getName());
declaringScope.addClassDescriptor(mutableClassDescriptor);
classes.put(klass, mutableClassDescriptor);
trace.recordDeclarationResolution(klass, mutableClassDescriptor);
declaringScopes.put(klass, declaringScope);
return mutableClassDescriptor.getUnsubstitutedMemberScope();
}
@@ -73,14 +73,29 @@ public class JavaDescriptorResolver {
PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope);
if (psiClass == null) {
return null;
PsiPackage psiPackage = javaFacade.findPackage(qualifiedName);
if (psiPackage == null) {
return null;
}
namespaceDescriptor = createJavaNamespaceDescriptor(psiPackage);
} else {
namespaceDescriptor = createJavaNamespaceDescriptor(psiClass);
}
namespaceDescriptor = createJavaNamespaceDescriptor(psiClass);
namespaceDescriptorCache.put(qualifiedName, namespaceDescriptor);
}
return namespaceDescriptor;
}
private NamespaceDescriptor createJavaNamespaceDescriptor(PsiPackage psiPackage) {
NamespaceDescriptor namespaceDescriptor = new NamespaceDescriptor(
Collections.<Attribute>emptyList(), // TODO
psiPackage.getName(),
new JavaPackageScope(psiPackage.getQualifiedName(), semanticServices)
);
semanticServices.getTrace().recordDeclarationResolution(psiPackage, namespaceDescriptor);
return namespaceDescriptor;
}
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull PsiClass psiClass) {
NamespaceDescriptor namespaceDescriptor = new NamespaceDescriptor(
Collections.<Attribute>emptyList(), // TODO
@@ -8,12 +8,14 @@ import org.jetbrains.jet.lang.types.NamespaceDescriptor;
/**
* @author abreslav
*/
public class JavaLangScope extends JetScopeImpl {
public class JavaPackageScope extends JetScopeImpl {
private final JavaSemanticServices semanticServices;
private String packagePrefix;
public JavaLangScope(JavaSemanticServices semanticServices) {
public JavaPackageScope(@NotNull String packageFQN, JavaSemanticServices semanticServices) {
this.semanticServices = semanticServices;
this.packagePrefix = packageFQN.isEmpty() ? "" : packageFQN + ".";
}
@Override
@@ -27,6 +29,6 @@ public class JavaLangScope extends JetScopeImpl {
}
private String getQualifiedName(String name) {
return "java.lang." + name;
return packagePrefix + name;
}
}
@@ -16,14 +16,27 @@ import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
/**
* @author abreslav
*/
public class JetStandardLibrary {
private final JetScope libraryScope;
// TODO : consider releasing this memory
private static final Map<Project, JetStandardLibrary> standardLibraryCache = new HashMap<Project, JetStandardLibrary>();
public static JetStandardLibrary getJetStandardLibrary(@NotNull Project project) {
JetStandardLibrary standardLibrary = standardLibraryCache.get(project);
if (standardLibrary == null) {
standardLibrary = new JetStandardLibrary(project);
standardLibraryCache.put(project, standardLibrary);
}
return standardLibrary;
}
private final JetScope libraryScope;
private final ClassDescriptor byteClass;
private final ClassDescriptor charClass;
private final ClassDescriptor shortClass;
@@ -44,7 +57,7 @@ public class JetStandardLibrary {
private final Type booleanType;
private final Type stringType;
public JetStandardLibrary(@NotNull Project project) {
private JetStandardLibrary(@NotNull Project project) {
// TODO : review
InputStream stream = JetStandardClasses.class.getClassLoader().getResourceAsStream("jet/lang/Library.jet");
try {
@@ -381,8 +381,10 @@ public class JetTypeInferrer {
JetReferenceExpression referenceExpression = (JetReferenceExpression) selectorExpression;
Type receiverType = getType(scope, expression.getReceiverExpression(), false);
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
reference[0] = referenceExpression;
if (receiverType != null) {
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
reference[0] = referenceExpression;
}
} else {
throw new UnsupportedOperationException(); // TODO
}
@@ -406,6 +408,7 @@ public class JetTypeInferrer {
throw new IllegalArgumentException("Unsupported element: " + elem);
}
});
if (result[0] == null) return OverloadDomain.EMPTY;
return new OverloadDomain() {
@Override
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
@@ -6,9 +6,8 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
@@ -77,10 +76,7 @@ public class ExpectedResolveData {
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
BindingTraceContext bindingTraceContext = new BindingTraceContext();
TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, bindingTraceContext);
topDownAnalyzer.process(lib.getLibraryScope(), file.getRootNamespace().getDeclarations());
BindingContext bindingContext = bindingTraceContext;
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, ErrorHandler.THROW_EXCEPTION);
Map<String, JetDeclaration> nameToDeclaration = new HashMap<String, JetDeclaration>();
@@ -32,7 +32,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
library = new JetStandardLibrary(getProject());
library = JetStandardLibrary.getJetStandardLibrary(getProject());
semanticServices = JetSemanticServices.createSemanticServices(library, ErrorHandler.DO_NOTHING);
classDefinitions = new ClassDefinitions();
classDescriptorResolver = semanticServices.getClassDescriptorResolver(BindingTrace.DUMMY);