diff --git a/annotations/com/intellij/psi/util/annotations.xml b/annotations/com/intellij/psi/util/annotations.xml index a89370620f5..bf2a653fb92 100644 --- a/annotations/com/intellij/psi/util/annotations.xml +++ b/annotations/com/intellij/psi/util/annotations.xml @@ -1,4 +1,8 @@ + + + diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 8ed033043bf..9b1200f9e2b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -234,7 +234,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { boolean isLocalOrAnonymousClass = isObjectLiteral || !(parentDescriptor instanceof NamespaceDescriptor || parentDescriptor instanceof ClassDescriptor); - if (isLocalOrAnonymousClass) { + // Do not emit enclosing method in "light-classes mode" since currently we genenerate local light classes as if they're top level + if (isLocalOrAnonymousClass && getState().getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) { String outerClassName = getOuterClassName(descriptor, typeMapper); FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java index 31591be2742..12e6f0d3ebf 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/MemberCodegen.java @@ -78,14 +78,15 @@ public class MemberCodegen extends ParentCodegenAwareImpl { public void genClassOrObject(CodegenContext parentContext, JetClassOrObject aClass) { ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); - if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) { - if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) { - throw new IllegalStateException( - "Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor); - } + if (descriptor == null || ErrorUtils.isError(descriptor)) { + badDescriptor(descriptor); return; } + if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) { + badDescriptor(descriptor); + } + ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile()); ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state); new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, this).generate(); @@ -98,4 +99,11 @@ public class MemberCodegen extends ParentCodegenAwareImpl { traitBuilder.done(); } } + + private void badDescriptor(ClassDescriptor descriptor) { + if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) { + throw new IllegalStateException( + "Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor); + } + } } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliJetFilesProvider.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliJetFilesProvider.java index 3aa4a5f7ae7..7559fdd5fd5 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliJetFilesProvider.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliJetFilesProvider.java @@ -45,6 +45,7 @@ public class CliJetFilesProvider extends JetFilesProvider { return allFiles; } + @NotNull @Override public List allInScope(@NotNull GlobalSearchScope scope) { List answer = new ArrayList(); diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java index 8e3460e7f4c..d97e6c7fa54 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliLightClassGenerationSupport.java @@ -82,10 +82,20 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport trace = null; } + private LightClassConstructionContext analyzeRelevantCode() { + return new LightClassConstructionContext(getTrace().getBindingContext(), null); + } + @NotNull @Override public LightClassConstructionContext analyzeRelevantCode(@NotNull Collection files) { - return new LightClassConstructionContext(getTrace().getBindingContext(), null); + return analyzeRelevantCode(); + } + + @NotNull + @Override + public LightClassConstructionContext analyzeRelevantCode(@NotNull JetClassOrObject classOrObject) { + return analyzeRelevantCode(); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java index c31e8ada068..13c4f8f9dd4 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java @@ -45,6 +45,7 @@ public abstract class JetFilesProvider { } public abstract Function> sampleToAllFilesInModule(); + @NotNull public abstract Collection allInScope(@NotNull GlobalSearchScope scope); public abstract boolean isFileInScope(@NotNull JetFile file, @NotNull GlobalSearchScope scope); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index 375d94b1cfe..84457d9fbd8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -570,10 +570,6 @@ public class JetPsiUtil { return statements.isEmpty() ? null : statements.get(statements.size() - 1); } - public static boolean isLocalClass(@NotNull JetClassOrObject classOrObject) { - return getOutermostClassOrObject(classOrObject) == null; - } - public static boolean isTrait(@NotNull JetClassOrObject classOrObject) { return classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait(); } @@ -595,7 +591,7 @@ public class JetPsiUtil { } if (!(parent instanceof JetClassBody)) { // It is a local class, no legitimate outer - return null; + return current; } current = (JetClassOrObject) parent.getParent(); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/GeneratedLightClassData.kt b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/GeneratedLightClassData.kt new file mode 100644 index 00000000000..e68849f8f23 --- /dev/null +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/GeneratedLightClassData.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.asJava + +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor +import org.jetbrains.jet.lang.resolve.BindingContext +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.descriptors.ClassDescriptor + +data class GeneratedLightClassData( + val javaFileStub: PsiJavaFileStub, + val jvmInternalName: String, + val descriptor: ClassDescriptor? +) diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java index 7f08d9ba171..9d17fee4dd9 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java @@ -37,20 +37,24 @@ import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.CompilationErrorHandler; import org.jetbrains.jet.codegen.NamespaceCodegen; +import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.Progress; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.lang.InlineUtil; import java.util.Collection; import java.util.Collections; -public class KotlinJavaFileStubProvider implements CachedValueProvider { +public class KotlinJavaFileStubProvider implements CachedValueProvider { @NotNull public static KotlinJavaFileStubProvider createForPackageClass( @@ -58,90 +62,131 @@ public class KotlinJavaFileStubProvider implements CachedValueProvider files) { + return LightClassGenerationSupport.getInstance(project).analyzeRelevantCode(files); + } - @NotNull - @Override - public Collection getFiles() { - // Don't memoize this, it can be called again after an out-of-code-block modification occurs, - // and the set of files changes - return LightClassGenerationSupport.getInstance(project).findFilesForPackage(packageFqName, searchScope); - } + @NotNull + @Override + public Collection getFiles() { + // Don't memoize this, it can be called again after an out-of-code-block modification occurs, + // and the set of files changes + return LightClassGenerationSupport.getInstance(project).findFilesForPackage(packageFqName, searchScope); + } - @NotNull - @Override - public FqName getPackageFqName() { - return packageFqName; - } + @NotNull + @Override + public GeneratedLightClassData createStubWithName(PsiJavaFileStub javaFileStub, BindingContext bindingContext) { + return new GeneratedLightClassData(javaFileStub, "", null); + } - @Override - public void generate(@NotNull GenerationState state, @NotNull Collection files) { - NamespaceCodegen codegen = state.getFactory().forNamespace(packageFqName, files); - codegen.generate(CompilationErrorHandler.THROW_EXCEPTION); - state.getFactory().asList(); - } - }); + @NotNull + @Override + public FqName getPackageFqName() { + return packageFqName; + } + + @Override + public void generate(@NotNull GenerationState state, @NotNull Collection files) { + NamespaceCodegen codegen = state.getFactory().forNamespace(packageFqName, files); + codegen.generate(CompilationErrorHandler.THROW_EXCEPTION); + state.getFactory().asList(); + } + } + ); } @NotNull - public static KotlinJavaFileStubProvider createForDeclaredTopLevelClass(@NotNull final JetClassOrObject classOrObject) { - return new KotlinJavaFileStubProvider(classOrObject.getProject(), new StubGenerationStrategy.WithDeclaredClasses() { - private JetFile getFile() { - JetFile file = (JetFile) classOrObject.getContainingFile(); - assert classOrObject.getParent() == file : "Not a top-level class: " + classOrObject.getText(); - return file; - } + public static KotlinJavaFileStubProvider createForDeclaredClass(@NotNull final JetClassOrObject classOrObject) { + return new KotlinJavaFileStubProvider( + classOrObject.getProject(), + JetPsiUtil.isLocal(classOrObject), + new StubGenerationStrategy.WithDeclaredClasses() { + private JetFile getFile() { + return (JetFile) classOrObject.getContainingFile(); + } - @NotNull - @Override - public Collection getFiles() { - return Collections.singletonList(getFile()); - } + @NotNull + @Override + public LightClassConstructionContext createLightClassConstructionContext(@NotNull Collection files) { + return LightClassGenerationSupport.getInstance(classOrObject.getProject()).analyzeRelevantCode(classOrObject); + } - @NotNull - @Override - public FqName getPackageFqName() { - return JetPsiUtil.getFQName(getFile()); - } + @NotNull + @Override + public GeneratedLightClassData createStubWithName(PsiJavaFileStub javaFileStub, BindingContext bindingContext) { + ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject); + assert (classDescriptor != null); - @Override - public void generate(@NotNull GenerationState state, @NotNull Collection files) { - NamespaceCodegen namespaceCodegen = state.getFactory().forNamespace(getPackageFqName(), files); - namespaceCodegen.generateClassOrObject(classOrObject); - state.getFactory().asList(); - } - }); + Type asmType = bindingContext.get(CodegenBinding.ASM_TYPE, classDescriptor); + assert (asmType != null); + + String jvmInternalName = asmType.getClassName(); + assert (jvmInternalName != null); + + return new GeneratedLightClassData(javaFileStub, jvmInternalName, classDescriptor); + } + + @NotNull + @Override + public Collection getFiles() { + return Collections.singletonList(getFile()); + } + + @NotNull + @Override + public FqName getPackageFqName() { + return JetPsiUtil.getFQName(getFile()); + } + + @Override + public void generate(@NotNull GenerationState state, @NotNull Collection files) { + NamespaceCodegen namespaceCodegen = state.getFactory().forNamespace(getPackageFqName(), files); + namespaceCodegen.generateClassOrObject(classOrObject); + state.getFactory().asList(); + } + } + ); } private static final Logger LOG = Logger.getInstance(KotlinJavaFileStubProvider.class); private final Project project; private final StubGenerationStrategy stubGenerationStrategy; + private final boolean local; private KotlinJavaFileStubProvider( @NotNull Project project, + boolean local, @NotNull StubGenerationStrategy stubGenerationStrategy ) { this.project = project; this.stubGenerationStrategy = stubGenerationStrategy; + this.local = local; } @Nullable @Override - public Result compute() { + public Result compute() { FqName packageFqName = stubGenerationStrategy.getPackageFqName(); Collection files = stubGenerationStrategy.getFiles(); checkForBuiltIns(packageFqName, files); - LightClassConstructionContext context = LightClassGenerationSupport.getInstance(project).analyzeRelevantCode(files); - + LightClassConstructionContext context = stubGenerationStrategy.createLightClassConstructionContext(files); Throwable error = context.getError(); if (error != null) { throw new IllegalStateException("failed to analyze: " + error, error); } PsiJavaFileStub javaFileStub = createJavaFileStub(packageFqName, getRepresentativeVirtualFile(files)); + BindingContext bindingContext; try { Stack stubStack = new Stack(); stubStack.push(javaFileStub); @@ -157,6 +202,8 @@ public class KotlinJavaFileStubProvider implements CachedValueProvider files); + @NotNull + GeneratedLightClassData createStubWithName(PsiJavaFileStub javaFileStub, BindingContext bindingContext); @NotNull Collection getFiles(); @NotNull FqName getPackageFqName(); boolean generateDeclaredClasses(); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java index 5c4715c7f74..c978d7f1a2b 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java @@ -42,7 +42,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -59,7 +59,7 @@ import java.util.List; import static org.jetbrains.jet.lexer.JetTokens.*; public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightClass implements KotlinLightClass, JetJavaMirrorMarker { - private final static Key> JAVA_API_STUB = Key.create("JAVA_API_STUB"); + private final static Key> JAVA_API_STUB = Key.create("JAVA_API_STUB"); @Nullable public static KotlinLightClassForExplicitDeclaration create(@NotNull PsiManager manager, @NotNull JetClassOrObject classOrObject) { @@ -67,18 +67,21 @@ public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightC return null; } - // TODO temporary not building light classes for local classes: e.g., they won't be visible in hierarchy - if (JetPsiUtil.getOutermostClassOrObject(classOrObject) == null) { - return null; - } - - String jvmInternalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject); + String jvmInternalName = getJvmInternalName(classOrObject); if (jvmInternalName == null) return null; FqName fqName = JvmClassName.byInternalName(jvmInternalName).getFqNameForClassNameWithoutDollars(); + return new KotlinLightClassForExplicitDeclaration(manager, fqName, classOrObject); } + private static String getJvmInternalName(JetClassOrObject classOrObject) { + if (JetPsiUtil.isLocal(classOrObject)) { + return getGeneratedLightClassData(classOrObject).getJvmInternalName(); + } + return PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject); + } + private final FqName classFqName; // FqName of (possibly inner) class private final JetClassOrObject classOrObject; private PsiClass delegate; @@ -153,12 +156,31 @@ public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightC @NotNull private PsiJavaFileStub getJavaFileStub() { + return getGeneratedLightClassData().getJavaFileStub(); + } + + @NotNull + private ClassDescriptor getDescriptor() { + ClassDescriptor descriptor = getGeneratedLightClassData().getDescriptor(); + assert descriptor != null; + + return descriptor; + } + + @NotNull + private GeneratedLightClassData getGeneratedLightClassData() { + return getGeneratedLightClassData(classOrObject); + } + + @NotNull + private static GeneratedLightClassData getGeneratedLightClassData(JetClassOrObject classOrObject) { JetClassOrObject outermostClassOrObject = getOutermostClassOrObject(classOrObject); - return CachedValuesManager.getManager(getProject()).getCachedValue( + return CachedValuesManager.getManager(classOrObject.getProject()).getCachedValue( outermostClassOrObject, JAVA_API_STUB, - KotlinJavaFileStubProvider.createForDeclaredTopLevelClass(outermostClassOrObject), - /*trackValue = */false); + KotlinJavaFileStubProvider.createForDeclaredClass(outermostClassOrObject), + /*trackValue = */false + ); } @NotNull @@ -392,6 +414,19 @@ public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightC return classOrObject.isValid(); } + @Override + public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) { + String qualifiedName; + if (baseClass instanceof KotlinLightClassForExplicitDeclaration) { + qualifiedName = DescriptorUtils.getFQName(((KotlinLightClassForExplicitDeclaration) baseClass).getDescriptor()).asString(); + } + else { + qualifiedName = baseClass.getQualifiedName(); + } + + return ResolvePackage.checkSuperTypeByFQName(getDescriptor(), qualifiedName, checkDeep); + } + @Override public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { throw new IncorrectOperationException("Cannot modify compiled kotlin element"); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForPackage.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForPackage.java index 978a17de48d..ee8f2fdad4e 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForPackage.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForPackage.java @@ -21,7 +21,6 @@ import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentationProviders; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; -import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; import com.intellij.psi.impl.light.LightEmptyImplementsList; import com.intellij.psi.impl.light.LightModifierList; import com.intellij.psi.javadoc.PsiDocComment; @@ -32,8 +31,8 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; +import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.JetLanguage; @@ -48,7 +47,7 @@ public class KotlinLightClassForPackage extends KotlinWrappingLightClass impleme private final GlobalSearchScope searchScope; private final Collection files; private final int hashCode; - private final CachedValue javaFileStub; + private final CachedValue javaFileStub; private final PsiModifierList modifierList; private final LightEmptyImplementsList implementsList; @@ -266,7 +265,7 @@ public class KotlinLightClassForPackage extends KotlinWrappingLightClass impleme @NotNull @Override public PsiClass getDelegate() { - PsiClass psiClass = LightClassUtil.findClass(packageClassFqName, javaFileStub.getValue()); + PsiClass psiClass = LightClassUtil.findClass(packageClassFqName, javaFileStub.getValue().getJavaFileStub()); if (psiClass == null) { throw new IllegalStateException("Package class was not found " + packageFqName); } diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java index 6512f21b581..00d0ea5cc41 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/LightClassGenerationSupport.java @@ -38,6 +38,9 @@ public abstract class LightClassGenerationSupport { @NotNull public abstract LightClassConstructionContext analyzeRelevantCode(@NotNull Collection files); + @NotNull + public abstract LightClassConstructionContext analyzeRelevantCode(@NotNull JetClassOrObject classOrObject); + @NotNull public abstract Collection findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope); diff --git a/compiler/tests/org/jetbrains/jet/lang/psi/JetPsiUtilTest.java b/compiler/tests/org/jetbrains/jet/lang/psi/JetPsiUtilTest.java index 5ea4003314c..5723a8141ee 100644 --- a/compiler/tests/org/jetbrains/jet/lang/psi/JetPsiUtilTest.java +++ b/compiler/tests/org/jetbrains/jet/lang/psi/JetPsiUtilTest.java @@ -78,10 +78,10 @@ public class JetPsiUtilTest extends JetLiteFixture { for (JetClassOrObject classOrObject : classOrObjects) { String classOrObjectName = classOrObject.getName(); if (classOrObjectName != null && classOrObjectName.contains("Local")) { - assertTrue("JetPsiUtil.isLocalClass should return true for " + classOrObjectName, JetPsiUtil.isLocalClass(classOrObject)); + assertTrue("JetPsiUtil.isLocalClass should return true for " + classOrObjectName, JetPsiUtil.isLocal(classOrObject)); } else { - assertFalse("JetPsiUtil.isLocalClass should return false for " + classOrObjectName, JetPsiUtil.isLocalClass(classOrObject)); + assertFalse("JetPsiUtil.isLocalClass should return false for " + classOrObjectName, JetPsiUtil.isLocal(classOrObject)); } } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/descriptorUtils.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/descriptorUtils.kt new file mode 100644 index 00000000000..dc30149567f --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/descriptorUtils.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve + +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor + +public fun ClassDescriptor.checkSuperTypeByFQName(qualifiedName: String, deep: Boolean): Boolean { + fun checkDescriptor(descriptor: DeclarationDescriptor): Boolean { + return qualifiedName == DescriptorUtils.getFQName(descriptor).asString() + } + + if (deep && checkDescriptor(this)) return true + + for (superType in getTypeConstructor().getSupertypes()) { + val superDescriptor = superType.getConstructor().getDeclarationDescriptor() + if (superDescriptor is ClassDescriptor) { + if (checkDescriptor(superDescriptor)) return true + if (deep && superDescriptor.checkSuperTypeByFQName(qualifiedName, deep)) return true + } + } + + return false +} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java index 5d6342d5ec3..c719dbbbc20 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/IDELightClassGenerationSupport.java @@ -67,6 +67,13 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport return new LightClassConstructionContext(declarationsCache.getBindingContext(), null); } + @NotNull + @Override + public LightClassConstructionContext analyzeRelevantCode(@NotNull JetClassOrObject classOrObject) { + KotlinCacheManager cacheManager = KotlinCacheManager.getInstance(project); + return new LightClassConstructionContext(cacheManager.getLightClassContextCache().getLightClassContext(classOrObject), null); + } + @NotNull @Override public Collection findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope) { diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java index 5c8da40892e..21dc4c50980 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java @@ -23,22 +23,26 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.DefaultModificationTracker; import com.intellij.openapi.util.ModificationTracker; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.asJava.KotlinLightClassContextCache; import org.jetbrains.jet.plugin.project.TargetPlatform; import java.util.Map; public class KotlinCacheManager { + @NotNull public static KotlinCacheManager getInstance(@NotNull Project project) { return ServiceManager.getService(project, KotlinCacheManager.class); } private final Map cacheProviders = Maps.newHashMap(); + private final KotlinLightClassContextCache lightClassContextCache; private final DefaultModificationTracker kotlinDeclarationsTracker = new DefaultModificationTracker(); public KotlinCacheManager(@NotNull Project project) { cacheProviders.put(TargetPlatform.JVM, new JvmDeclarationsCacheProvider(project)); cacheProviders.put(TargetPlatform.JS, new JSDeclarationsCacheProvider(project)); + lightClassContextCache = new KotlinLightClassContextCache(project); } /** @@ -84,6 +88,10 @@ public class KotlinCacheManager { return provider; } + public KotlinLightClassContextCache getLightClassContextCache() { + return lightClassContextCache; + } + public void invalidateCache() { kotlinDeclarationsTracker.incModificationCount(); } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinLightClassContextCache.kt b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinLightClassContextCache.kt new file mode 100644 index 00000000000..ad4bacdfe6a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinLightClassContextCache.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.asJava + +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.util.CachedValueProvider.Result +import org.jetbrains.jet.lang.resolve.BindingContext +import org.jetbrains.jet.lang.psi.JetClassOrObject +import com.intellij.openapi.project.Project +import org.jetbrains.jet.lang.psi.JetPsiUtil +import com.intellij.openapi.util.Key +import java.util.HashMap +import com.intellij.psi.util.PsiModificationTracker +import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager +import org.jetbrains.jet.lang.psi.JetDeclaration +import org.jetbrains.jet.lang.psi.JetNamedFunction +import org.jetbrains.jet.lang.psi.JetProperty +import org.jetbrains.jet.lang.psi.JetClassInitializer +import org.jetbrains.jet.plugin.project.ResolveElementCache +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM +import java.util.Collections +import org.jetbrains.jet.lang.psi.JetFile +import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.CachedValue +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace +import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver +import org.jetbrains.jet.lang.resolve.java.JetFilesProvider +import com.intellij.psi.search.GlobalSearchScope + +class KotlinLightClassContextCache(val project: Project) { + private val cacheKey = Key.create>("KOTLIN_LIGHT_CLASS_CONTEXT_CACHE") + + private val lock = Any() + + private val provider = object: CachedValueProvider { + override fun compute(): CachedValueProvider.Result { + val trace = DelegatingBindingTrace( + KotlinCacheManager.getInstance(project).getPossiblyIncompleteDeclarationsForLightClassGeneration().getBindingContext(), + "Trace for KotlinLightClassContextCache" + ) + val resolveSession = AnalyzerFacadeForJVM.createLazyResolveSession( + project, + JetFilesProvider.getInstance(project)!!.allInScope(GlobalSearchScope.allScope(project)), + trace, + InjectorForJavaDescriptorResolver(project, trace), + true + ) + return Result.create( + ResolveElementCache(resolveSession, project), + PsiModificationTracker.MODIFICATION_COUNT, + KotlinCacheManager.getInstance(project).getDeclarationsTracker() + ) + } + } + + public fun getLightClassContext(classOrObject: JetClassOrObject): BindingContext { + if (!JetPsiUtil.isLocal(classOrObject)) { + return KotlinCacheManager.getInstance(project).getPossiblyIncompleteDeclarationsForLightClassGeneration().getBindingContext() + } + + val resolveElementCache = CachedValuesManager.getManager(project).getCachedValue(project, cacheKey, provider, false) + return resolveElementCache?.resolveElement(classOrObject) ?: BindingContext.EMPTY + } + +} diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java index a10095ee7c5..4329a2e2ff0 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java @@ -360,7 +360,7 @@ public class JetSourceNavigationHelper { } } } - return JetPsiUtil.isLocalClass(classOrObject) ? null : LightClassUtil.getPsiClass(classOrObject); + return LightClassUtil.getPsiClass(classOrObject); } @Nullable diff --git a/idea/src/org/jetbrains/jet/plugin/project/PluginJetFilesProvider.java b/idea/src/org/jetbrains/jet/plugin/project/PluginJetFilesProvider.java index ad6ec19d663..9dfd6dea82d 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/PluginJetFilesProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/project/PluginJetFilesProvider.java @@ -117,6 +117,7 @@ public class PluginJetFilesProvider extends JetFilesProvider { !JetPluginUtil.isKtFileInGradleProjectInWrongFolder(virtualFile, project); } + @NotNull @Override public Collection allInScope(@NotNull GlobalSearchScope scope) { return cache.getValue(scope); diff --git a/idea/src/org/jetbrains/jet/plugin/search/KotlinDirectInheritorsSearcher.java b/idea/src/org/jetbrains/jet/plugin/search/KotlinDirectInheritorsSearcher.java index c160f525282..6e57ff74bfa 100644 --- a/idea/src/org/jetbrains/jet/plugin/search/KotlinDirectInheritorsSearcher.java +++ b/idea/src/org/jetbrains/jet/plugin/search/KotlinDirectInheritorsSearcher.java @@ -26,12 +26,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.libraries.JetSourceNavigationHelper; -import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.plugin.search.usagesSearch.UsagesSearchPackage; import org.jetbrains.jet.plugin.stubindex.JetSuperClassIndex; import java.util.Collection; @@ -60,9 +58,9 @@ public class KotlinDirectInheritorsSearcher extends QueryExecutorBase candidates = JetSuperClassIndex.getInstance().get(name, clazz.getProject(), scope); for (JetClassOrObject candidate : candidates) { - JetFile containingFile = (JetFile) candidate.getContainingFile(); - KotlinCodeAnalyzer sessionForFile = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(containingFile); - ClassDescriptor classDescriptor = (ClassDescriptor) sessionForFile.resolveToDescriptor(candidate); + ClassDescriptor classDescriptor = (ClassDescriptor) UsagesSearchPackage.getDescriptor(candidate); + if (classDescriptor == null) continue; + for (JetType type : classDescriptor.getTypeConstructor().getSupertypes()) { ClassifierDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor != null) {