Add support of light classes for local class/object declarations
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
<root>
|
||||
<item
|
||||
name='com.intellij.psi.util.CachedValueProvider.Result com.intellij.psi.util.CachedValueProvider.Result<T> create(T, java.lang.Object...)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.psi.util.CachedValuesManager com.intellij.psi.util.CachedValue<T> createCachedValue(com.intellij.psi.util.CachedValueProvider<T>, boolean)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public class CliJetFilesProvider extends JetFilesProvider {
|
||||
return allFiles;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetFile> allInScope(@NotNull GlobalSearchScope scope) {
|
||||
List<JetFile> answer = new ArrayList<JetFile>();
|
||||
|
||||
+11
-1
@@ -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<JetFile> files) {
|
||||
return new LightClassConstructionContext(getTrace().getBindingContext(), null);
|
||||
return analyzeRelevantCode();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LightClassConstructionContext analyzeRelevantCode(@NotNull JetClassOrObject classOrObject) {
|
||||
return analyzeRelevantCode();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -45,6 +45,7 @@ public abstract class JetFilesProvider {
|
||||
}
|
||||
|
||||
public abstract Function<JetFile, Collection<JetFile>> sampleToAllFilesInModule();
|
||||
@NotNull
|
||||
public abstract Collection<JetFile> allInScope(@NotNull GlobalSearchScope scope);
|
||||
public abstract boolean isFileInScope(@NotNull JetFile file, @NotNull GlobalSearchScope scope);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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?
|
||||
)
|
||||
+102
-49
@@ -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<PsiJavaFileStub> {
|
||||
public class KotlinJavaFileStubProvider implements CachedValueProvider<GeneratedLightClassData> {
|
||||
|
||||
@NotNull
|
||||
public static KotlinJavaFileStubProvider createForPackageClass(
|
||||
@@ -58,90 +62,131 @@ public class KotlinJavaFileStubProvider implements CachedValueProvider<PsiJavaFi
|
||||
@NotNull final FqName packageFqName,
|
||||
@NotNull final GlobalSearchScope searchScope
|
||||
) {
|
||||
return new KotlinJavaFileStubProvider(project, new StubGenerationStrategy.NoDeclaredClasses() {
|
||||
return new KotlinJavaFileStubProvider(
|
||||
project,
|
||||
false,
|
||||
new StubGenerationStrategy.NoDeclaredClasses() {
|
||||
@NotNull
|
||||
@Override
|
||||
public LightClassConstructionContext createLightClassConstructionContext(@NotNull Collection<JetFile> files) {
|
||||
return LightClassGenerationSupport.getInstance(project).analyzeRelevantCode(files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetFile> 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<JetFile> 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<JetFile> 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<JetFile> 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<JetFile> getFiles() {
|
||||
return Collections.singletonList(getFile());
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
public LightClassConstructionContext createLightClassConstructionContext(@NotNull Collection<JetFile> 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<JetFile> 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<JetFile> getFiles() {
|
||||
return Collections.singletonList(getFile());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getPackageFqName() {
|
||||
return JetPsiUtil.getFQName(getFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull GenerationState state, @NotNull Collection<JetFile> 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<PsiJavaFileStub> compute() {
|
||||
public Result<GeneratedLightClassData> compute() {
|
||||
FqName packageFqName = stubGenerationStrategy.getPackageFqName();
|
||||
Collection<JetFile> 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<StubElement> stubStack = new Stack<StubElement>();
|
||||
stubStack.push(javaFileStub);
|
||||
@@ -157,6 +202,8 @@ public class KotlinJavaFileStubProvider implements CachedValueProvider<PsiJavaFi
|
||||
InlineUtil.DEFAULT_INLINE_FLAG_FOR_STUB);
|
||||
state.beforeCompile();
|
||||
|
||||
bindingContext = state.getBindingContext();
|
||||
|
||||
stubGenerationStrategy.generate(state, files);
|
||||
|
||||
StubElement pop = stubStack.pop();
|
||||
@@ -173,7 +220,10 @@ public class KotlinJavaFileStubProvider implements CachedValueProvider<PsiJavaFi
|
||||
throw e;
|
||||
}
|
||||
|
||||
return Result.create(javaFileStub, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
return Result.create(
|
||||
stubGenerationStrategy.createStubWithName(javaFileStub, bindingContext),
|
||||
local ? PsiModificationTracker.MODIFICATION_COUNT : PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -231,6 +281,9 @@ public class KotlinJavaFileStubProvider implements CachedValueProvider<PsiJavaFi
|
||||
}
|
||||
|
||||
private interface StubGenerationStrategy {
|
||||
@NotNull LightClassConstructionContext createLightClassConstructionContext(@NotNull Collection<JetFile> files);
|
||||
@NotNull
|
||||
GeneratedLightClassData createStubWithName(PsiJavaFileStub javaFileStub, BindingContext bindingContext);
|
||||
@NotNull Collection<JetFile> getFiles();
|
||||
@NotNull FqName getPackageFqName();
|
||||
boolean generateDeclaredClasses();
|
||||
|
||||
+46
-11
@@ -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<CachedValue<PsiJavaFileStub>> JAVA_API_STUB = Key.create("JAVA_API_STUB");
|
||||
private final static Key<CachedValue<GeneratedLightClassData>> 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");
|
||||
|
||||
+3
-4
@@ -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<JetFile> files;
|
||||
private final int hashCode;
|
||||
private final CachedValue<PsiJavaFileStub> javaFileStub;
|
||||
private final CachedValue<GeneratedLightClassData> 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);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ public abstract class LightClassGenerationSupport {
|
||||
@NotNull
|
||||
public abstract LightClassConstructionContext analyzeRelevantCode(@NotNull Collection<JetFile> files);
|
||||
|
||||
@NotNull
|
||||
public abstract LightClassConstructionContext analyzeRelevantCode(@NotNull JetClassOrObject classOrObject);
|
||||
|
||||
@NotNull
|
||||
public abstract Collection<JetClassOrObject> findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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<JetClassOrObject> findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope) {
|
||||
|
||||
@@ -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<TargetPlatform, DeclarationsCacheProvider> 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();
|
||||
}
|
||||
|
||||
@@ -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<CachedValue<ResolveElementCache>>("KOTLIN_LIGHT_CLASS_CONTEXT_CACHE")
|
||||
|
||||
private val lock = Any()
|
||||
|
||||
private val provider = object: CachedValueProvider<ResolveElementCache> {
|
||||
override fun compute(): CachedValueProvider.Result<ResolveElementCache> {
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -360,7 +360,7 @@ public class JetSourceNavigationHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
return JetPsiUtil.isLocalClass(classOrObject) ? null : LightClassUtil.getPsiClass(classOrObject);
|
||||
return LightClassUtil.getPsiClass(classOrObject);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -117,6 +117,7 @@ public class PluginJetFilesProvider extends JetFilesProvider {
|
||||
!JetPluginUtil.isKtFileInGradleProjectInWrongFolder(virtualFile, project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetFile> allInScope(@NotNull GlobalSearchScope scope) {
|
||||
return cache.getValue(scope);
|
||||
|
||||
@@ -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<PsiClass,
|
||||
GlobalSearchScope scope = (GlobalSearchScope) queryParameters.getScope();
|
||||
Collection<JetClassOrObject> 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) {
|
||||
|
||||
Reference in New Issue
Block a user