KT-689 Allow to put Java and Kotlin files in the same packages

This commit is contained in:
Andrey Breslav
2011-12-06 14:43:10 +04:00
parent 47050a11d1
commit deb8d5ea20
27 changed files with 219 additions and 171 deletions
@@ -0,0 +1,29 @@
package org.jetbrains.jet.lang;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
/**
* @author abreslav
*/
public interface Configuration {
Configuration EMPTY = new Configuration() {
@Override
public void addDefaultImports(BindingTrace trace, WritableScope rootScope) {
}
@Override
public void extendNamespaceScope(BindingTrace trace, @NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope) {
}
};
void addDefaultImports(BindingTrace trace, WritableScope rootScope);
/**
*
* This method is called every time a namespace descriptor is created. Use it to add extra descriptors to the namespace, e.g. merge a Java package with a Kotlin one
*/
void extendNamespaceScope(BindingTrace trace, @NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope);
}
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Maps;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
@@ -10,6 +9,7 @@ import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.Configuration;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.*;
@@ -17,20 +17,24 @@ 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.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class AnalyzingUtils {
public static AnalyzingUtils getInstance(@NotNull ImportingStrategy importingStrategy) {
return new AnalyzingUtils(importingStrategy);
private static final AnalyzingUtils INSTANCE = new AnalyzingUtils();
public static AnalyzingUtils getInstance() {
return INSTANCE;
}
public static void checkForSyntacticErrors(@NotNull PsiElement root) {
@@ -69,32 +73,26 @@ public class AnalyzingUtils {
}
}
private final ImportingStrategy importingStrategy;
private AnalyzingUtils(ImportingStrategy importingStrategy) {
this.importingStrategy = importingStrategy;
}
public BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
Project project = namespace.getProject();
List<JetDeclaration> declarations = Collections.<JetDeclaration>singletonList(namespace);
return analyzeNamespaces(project, declarations, Predicates.equalTo(namespace.getContainingFile()), flowDataTraceFactory);
}
// --------------------------------------------------------------------------------------------------------------------------
public BindingContext analyzeNamespaces(
@NotNull Project project,
@NotNull Configuration configuration,
@NotNull Collection<? extends JetDeclaration> declarations,
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
BindingTraceContext bindingTraceContext = new BindingTraceContext();
return analyzeNamespacesWithGivenTrace(project, configuration, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext);
}
public BindingContext analyzeNamespacesWithGivenTrace(Project project, Configuration configuration, Collection<? extends JetDeclaration> declarations, Predicate<PsiFile> filesToAnalyzeCompletely, JetControlFlowDataTraceFactory flowDataTraceFactory, BindingTraceContext bindingTraceContext) {
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project);
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope();
ModuleDescriptor owner = new ModuleDescriptor("<module>");
final WritableScope scope = new WritableScopeImpl(JetScope.EMPTY, owner, new TraceBasedRedeclarationHandler(bindingTraceContext)).setDebugName("Root scope in analyzeNamespace");
importingStrategy.addImports(project, semanticServices, bindingTraceContext, scope);
// configuration.addImports(project, semanticServices, bindingTraceContext, scope);
scope.importScope(libraryScope);
scope.changeLockLevel(WritableScope.LockLevel.BOTH);
@@ -132,29 +130,8 @@ public class AnalyzingUtils {
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
}
}, declarations, filesToAnalyzeCompletely, flowDataTraceFactory);
}, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, configuration);
return bindingTraceContext.getBindingContext();
}
public BindingContext shallowAnalyzeFiles(Collection<PsiFile> files) {
assert files.size() > 0;
Project project = files.iterator().next().getProject();
Collection<JetNamespace> namespaces = collectRootNamespaces(files);
return analyzeNamespaces(project, namespaces, Predicates.<PsiFile>alwaysFalse(), JetControlFlowDataTraceFactory.EMPTY);
}
public static List<JetNamespace> collectRootNamespaces(Collection<PsiFile> files) {
List<JetNamespace> namespaces = new ArrayList<JetNamespace>();
for (PsiFile file : files) {
if (file instanceof JetFile) {
namespaces.add(((JetFile) file).getRootNamespace());
}
}
return namespaces;
}
}
@@ -154,4 +154,14 @@ public class DescriptorUtils {
}
return false;
}
public static String getFQName(DeclarationDescriptor descriptor) {
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container != null && !(container instanceof ModuleDescriptor)) {
String baseName = getFQName(container);
if (!baseName.isEmpty()) return baseName + "." + descriptor.getName();
}
return descriptor.getName();
}
}
@@ -1,19 +0,0 @@
package org.jetbrains.jet.lang.resolve;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
/**
* @author abreslav
*/
public interface ImportingStrategy {
ImportingStrategy NONE = new ImportingStrategy() {
@Override
public void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope) {
}
};
void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope);
}
@@ -1,18 +1,13 @@
package org.jetbrains.jet.lang.resolve;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED;
@@ -51,7 +46,7 @@ public class OverloadResolver {
}
Key(NamespaceDescriptor namespaceDescriptor, String name) {
this(DescriptorRenderer.getFQName(namespaceDescriptor), name);
this(DescriptorUtils.getFQName(namespaceDescriptor), name);
}
public String getNamespace() {
@@ -6,6 +6,7 @@ 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.Configuration;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
@@ -23,31 +24,31 @@ import java.util.Set;
private final ObservableBindingTrace trace;
private final JetSemanticServices semanticServices;
private final DescriptorResolver descriptorResolver;
private final Configuration configuration;
private final DescriptorResolver descriptorResolver;
private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap();
private final Map<JetObjectDeclaration, MutableClassDescriptor> objects = Maps.newLinkedHashMap();
protected final Map<JetNamespace, WritableScope> namespaceScopes = Maps.newHashMap();
protected final Map<JetNamespace, NamespaceDescriptorImpl> namespaceDescriptors = Maps.newHashMap();
private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
private final Map<JetNamedFunction, FunctionDescriptorImpl> functions = Maps.newLinkedHashMap();
private final Map<JetSecondaryConstructor, ConstructorDescriptor> constructors = Maps.newLinkedHashMap();
private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
private final Set<PropertyDescriptor> primaryConstructorParameterProperties = Sets.newHashSet();
private final Predicate<PsiFile> analyzeCompletely;
private StringBuilder debugOutput;
private StringBuilder debugOutput;
private boolean analyzingBootstrapLibrary = false;
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate<PsiFile> analyzeCompletely) {
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate<PsiFile> analyzeCompletely, @NotNull Configuration configuration) {
this.trace = new ObservableBindingTrace(trace);
this.semanticServices = semanticServices;
this.descriptorResolver = semanticServices.getClassDescriptorResolver(trace);
this.analyzeCompletely = analyzeCompletely;
this.configuration = configuration;
}
public void debug(Object message) {
@@ -133,4 +134,8 @@ import java.util.Set;
return functions;
}
@NotNull
public Configuration getConfiguration() {
return configuration;
}
}
@@ -4,6 +4,7 @@ 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.Configuration;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.*;
@@ -30,8 +31,10 @@ public class TopDownAnalyzer {
@NotNull NamespaceLike owner,
@NotNull Collection<? extends JetDeclaration> declarations,
@NotNull Predicate<PsiFile> analyzeCompletely,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
process(semanticServices, trace, outerScope, owner, declarations, analyzeCompletely, flowDataTraceFactory, false);
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull Configuration configuration
) {
process(semanticServices, trace, outerScope, owner, declarations, analyzeCompletely, flowDataTraceFactory, configuration, false);
}
private static void process(
@@ -42,8 +45,9 @@ public class TopDownAnalyzer {
@NotNull Collection<? extends JetDeclaration> declarations,
@NotNull Predicate<PsiFile> analyzeCompletely,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull Configuration configuration,
boolean declaredLocally) {
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely);
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely, configuration);
doProcess(context, outerScope, owner, declarations, flowDataTraceFactory, declaredLocally);
}
@@ -89,7 +93,7 @@ public class TopDownAnalyzer {
@NotNull JetSemanticServices semanticServices,
@NotNull BindingTrace trace,
@NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull JetNamespace namespace) {
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.<PsiFile>alwaysTrue());
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.<PsiFile>alwaysTrue(), Configuration.EMPTY);
context.getNamespaceScopes().put(namespace, standardLibraryNamespace.getMemberScope());
context.getNamespaceDescriptors().put(namespace, standardLibraryNamespace);
context.getDeclaringScopes().put(namespace, outerScope);
@@ -135,7 +139,7 @@ public class TopDownAnalyzer {
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
return ClassObjectStatus.NOT_ALLOWED;
}
}, Collections.<JetDeclaration>singletonList(object), Predicates.equalTo(object.getContainingFile()), JetControlFlowDataTraceFactory.EMPTY, true);
}, Collections.<JetDeclaration>singletonList(object), Predicates.equalTo(object.getContainingFile()), JetControlFlowDataTraceFactory.EMPTY, Configuration.EMPTY, true);
}
}
@@ -75,6 +75,7 @@ public class TypeHierarchyResolver {
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace()));
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
context.getNamespaceScopes().put(namespace, namespaceScope);
context.getDeclaringScopes().put(namespace, outerScope);
@@ -215,6 +216,7 @@ public class TypeHierarchyResolver {
WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope");
scope.changeLockLevel(WritableScope.LockLevel.BOTH);
namespaceDescriptor.initialize(scope);
context.getConfiguration().extendNamespaceScope(context.getTrace(), namespaceDescriptor, scope);
owner.addNamespace(namespaceDescriptor);
if (namespace != null) {
context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor);
@@ -38,7 +38,7 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement
@Override
public WritableScope changeLockLevel(LockLevel lockLevel) {
if (lockLevel.ordinal() < this.lockLevel.ordinal()) {
throw new IllegalStateException("cannot lower lock level from " + this.lockLevel + " to " + lockLevel);
throw new IllegalStateException("cannot lower lock level from " + this.lockLevel + " to " + lockLevel + " at " + debugName);
}
this.lockLevel = lockLevel;
return this;
@@ -46,13 +46,13 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement
protected void checkMayRead() {
if (lockLevel != LockLevel.READING && lockLevel != LockLevel.BOTH) {
throw new IllegalStateException("cannot read with lock level " + lockLevel);
throw new IllegalStateException("cannot read with lock level " + lockLevel + " at " + debugName);
}
}
protected void checkMayWrite() {
if (lockLevel != LockLevel.WRITING && lockLevel != LockLevel.BOTH) {
throw new IllegalStateException("cannot write with lock level " + lockLevel);
throw new IllegalStateException("cannot write with lock level " + lockLevel + " at " + debugName);
}
}
@@ -18,16 +18,6 @@ import java.util.List;
*/
public class DescriptorRenderer implements Renderer {
public static String getFQName(DeclarationDescriptor descriptor) {
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container != null && !(container instanceof ModuleDescriptor)) {
String baseName = getFQName(container);
if (!baseName.isEmpty()) return baseName + "." + descriptor.getName();
}
return descriptor.getName();
}
public static final DescriptorRenderer TEXT = new DescriptorRenderer();
public static final DescriptorRenderer HTML = new DescriptorRenderer() {