KT-9721:
- Kotlin/JS still uses package facades. Handle them properly in StubClassBuilder parentStack. - Generate backend-related diagnostics in IDE using light class generation for file facades. - Drop PackageFacadeStubCache.
This commit is contained in:
@@ -370,7 +370,6 @@ public class KotlinCoreEnvironment private constructor(
|
||||
with (projectEnvironment.getProject()) {
|
||||
registerService(javaClass<JetScriptDefinitionProvider>(), JetScriptDefinitionProvider())
|
||||
registerService(javaClass<KotlinJavaPsiFacade>(), KotlinJavaPsiFacade(this))
|
||||
registerService(javaClass<KotlinLightClassForFacade.PackageFacadeStubCache>(), KotlinLightClassForFacade.PackageFacadeStubCache(this))
|
||||
registerService(javaClass<KotlinLightClassForFacade.FacadeStubCache>(), KotlinLightClassForFacade.FacadeStubCache(this))
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.fileClasses
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
|
||||
|
||||
+1
-83
@@ -70,88 +70,6 @@ import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToD
|
||||
|
||||
public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostics> implements CachedValueProvider<T> {
|
||||
|
||||
@NotNull
|
||||
public static KotlinJavaFileStubProvider<KotlinFacadeLightClassData> createForPackageClass(
|
||||
@NotNull final Project project,
|
||||
@NotNull final FqName packageFqName,
|
||||
@NotNull final GlobalSearchScope searchScope
|
||||
) {
|
||||
return new KotlinJavaFileStubProvider<KotlinFacadeLightClassData>(
|
||||
project,
|
||||
false,
|
||||
new StubGenerationStrategy<KotlinFacadeLightClassData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public LightClassConstructionContext getContext(@NotNull Collection<KtFile> files) {
|
||||
return LightClassGenerationSupport.getInstance(project).getContextForPackage(files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<KtFile> 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 KotlinFacadeLightClassData createLightClassData(
|
||||
PsiJavaFileStub javaFileStub,
|
||||
BindingContext bindingContext,
|
||||
Diagnostics extraDiagnostics
|
||||
) {
|
||||
return new KotlinFacadeLightClassData(javaFileStub, extraDiagnostics);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getPackageFqName() {
|
||||
return packageFqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||
return new GenerationState.GenerateClassFilter() {
|
||||
|
||||
@Override
|
||||
public boolean shouldGeneratePackagePart(KtFile jetFile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAnnotateClass(KtClassOrObject classOrObject) {
|
||||
return shouldGenerateClass(classOrObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateClass(KtClassOrObject classOrObject) {
|
||||
// Top-level classes and such should not be generated for performance reasons.
|
||||
// Local classes in top-level functions must still be generated
|
||||
return KtPsiUtil.isLocal(classOrObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateScript(KtScript script) {
|
||||
// Scripts yield top-level classes, and should not be generated
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull GenerationState state, @NotNull Collection<KtFile> files) {
|
||||
KotlinCodegenFacade.doGenerateFiles(files, state, CompilationErrorHandler.THROW_EXCEPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StubGenerationStrategy.class.getName() + " for package class";
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CachedValueProvider<KotlinFacadeLightClassData> createForFacadeClass(
|
||||
@NotNull final Project project,
|
||||
@@ -219,7 +137,7 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
||||
public void generate(@NotNull GenerationState state, @NotNull Collection<KtFile> files) {
|
||||
if (!files.isEmpty()) {
|
||||
KtFile representativeFile = files.iterator().next();
|
||||
JvmFileClassInfo fileClassInfo = NoResolveFileClassesProvider.INSTANCE$.getFileClassInfo(representativeFile);
|
||||
JvmFileClassInfo fileClassInfo = NoResolveFileClassesProvider.INSTANCE.getFileClassInfo(representativeFile);
|
||||
if (!fileClassInfo.getWithJvmMultifileClass()) {
|
||||
PackageCodegen codegen = state.getFactory().forPackage(representativeFile.getPackageFqName(), files);
|
||||
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION);
|
||||
|
||||
@@ -46,33 +46,6 @@ public class KotlinLightClassForFacade private constructor(
|
||||
|
||||
private data class StubCacheKey(val fqName: FqName, val searchScope: GlobalSearchScope)
|
||||
|
||||
public class PackageFacadeStubCache(private val project: Project) {
|
||||
private inner class PackageFacadeCacheData {
|
||||
val cache = object : SLRUCache<StubCacheKey, CachedValue<KotlinFacadeLightClassData>>(20, 30) {
|
||||
override fun createValue(key: StubCacheKey): CachedValue<KotlinFacadeLightClassData> {
|
||||
val stubProvider = KotlinJavaFileStubProvider.createForPackageClass(project, key.fqName, key.searchScope)
|
||||
return CachedValuesManager.getManager(project).createCachedValue<KotlinFacadeLightClassData>(stubProvider, /*trackValue = */false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val cachedValue: CachedValue<PackageFacadeCacheData> = CachedValuesManager.getManager(project).createCachedValue<PackageFacadeCacheData>(
|
||||
{ CachedValueProvider.Result.create(PackageFacadeCacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) },
|
||||
/*trackValue = */ false)
|
||||
|
||||
public fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<KotlinFacadeLightClassData> {
|
||||
synchronized (cachedValue) {
|
||||
return cachedValue.getValue().cache.get(StubCacheKey(qualifiedName, searchScope))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
public fun getInstance(project: Project): PackageFacadeStubCache {
|
||||
return ServiceManager.getService<PackageFacadeStubCache>(project, javaClass<PackageFacadeStubCache>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FacadeStubCache(private val project: Project) {
|
||||
private inner class FacadeCacheData {
|
||||
val cache = object : SLRUCache<StubCacheKey, CachedValue<KotlinFacadeLightClassData>>(20, 30) {
|
||||
|
||||
@@ -25,6 +25,9 @@ import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.AbstractClassBuilder;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
@@ -47,6 +50,7 @@ public class StubClassBuilder extends AbstractClassBuilder {
|
||||
private final StubElement parent;
|
||||
private StubBuildingVisitor v;
|
||||
private final Stack<StubElement> parentStack;
|
||||
private boolean isPackageClass = false;
|
||||
|
||||
public StubClassBuilder(@NotNull Stack<StubElement> parentStack) {
|
||||
this.parentStack = parentStack;
|
||||
@@ -75,7 +79,18 @@ public class StubClassBuilder extends AbstractClassBuilder {
|
||||
|
||||
super.defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||
|
||||
parentStack.push(v.getResult());
|
||||
if (origin instanceof KtFile) {
|
||||
FqName packageName = ((KtFile) origin).getPackageFqName();
|
||||
String packageClassName = PackageClassUtils.getPackageClassName(packageName);
|
||||
|
||||
if (name.equals(packageClassName) || name.endsWith("/" + packageClassName)) {
|
||||
isPackageClass = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isPackageClass) {
|
||||
parentStack.push(v.getResult());
|
||||
}
|
||||
|
||||
((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
}
|
||||
@@ -134,8 +149,10 @@ public class StubClassBuilder extends AbstractClassBuilder {
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
StubElement pop = parentStack.pop();
|
||||
assert pop == v.getResult();
|
||||
if (!isPackageClass) {
|
||||
StubElement pop = parentStack.pop();
|
||||
assert pop == v.getResult() : "parentStack: got " + pop + ", expected " + v.getResult();
|
||||
}
|
||||
super.done();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,14 +26,16 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
public fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics, moduleScope: GlobalSearchScope): Diagnostics? {
|
||||
fun getDiagnosticsForPackage(file: KtFile): Diagnostics? {
|
||||
val project = file.getProject()
|
||||
val cache = KotlinLightClassForFacade.PackageFacadeStubCache.getInstance(project)
|
||||
return cache[file.getPackageFqName(), moduleScope].getValue()?.extraDiagnostics
|
||||
fun getDiagnosticsForFileFacade(file: KtFile): Diagnostics? {
|
||||
val project = file.project
|
||||
val cache = KotlinLightClassForFacade.FacadeStubCache.getInstance(project)
|
||||
val facadeFqName = NoResolveFileClassesProvider.getFileClassInfo(file).facadeClassFqName
|
||||
return cache[facadeFqName, moduleScope].getValue()?.extraDiagnostics
|
||||
}
|
||||
|
||||
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
|
||||
@@ -58,7 +60,7 @@ public fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Dia
|
||||
|
||||
when (parent) {
|
||||
is KtFile -> {
|
||||
return getDiagnosticsForPackage(parent)
|
||||
return getDiagnosticsForFileFacade(parent)
|
||||
}
|
||||
is KtClassBody -> {
|
||||
val parentsParent = parent.getParent()
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public final class PackageClassUtils {
|
||||
|
||||
// ex. <root> -> _DefaultPackage, a -> APackage, a.b -> BPackage
|
||||
@NotNull
|
||||
private static String getPackageClassName(@NotNull FqName packageFQN) {
|
||||
public static String getPackageClassName(@NotNull FqName packageFQN) {
|
||||
if (packageFQN.isRoot()) {
|
||||
return DEFAULT_PACKAGE_CLASS_NAME;
|
||||
}
|
||||
|
||||
@@ -246,9 +246,6 @@
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.versions.SuppressNotificationState"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.asJava.KotlinLightClassForFacade$PackageFacadeStubCache"
|
||||
serviceImplementation="org.jetbrains.kotlin.asJava.KotlinLightClassForFacade$PackageFacadeStubCache"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.asJava.KotlinLightClassForFacade$FacadeStubCache"
|
||||
serviceImplementation="org.jetbrains.kotlin.asJava.KotlinLightClassForFacade$FacadeStubCache"/>
|
||||
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
@file:JvmName("TopLevelMultifile")
|
||||
@file:JvmMultifileClass
|
||||
package test
|
||||
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmMultifileClass
|
||||
|
||||
<error descr="[CONFLICTING_JVM_DECLARATIONS] Platform declaration clash: The following declarations have the same JVM signature (getX()I):
|
||||
fun <get-x>(): kotlin.Int
|
||||
fun getX(): kotlin.Int">val x</error> = 1
|
||||
<error descr="[CONFLICTING_JVM_DECLARATIONS] Platform declaration clash: The following declarations have the same JVM signature (getX()I):
|
||||
fun <get-x>(): kotlin.Int
|
||||
fun getX(): kotlin.Int">fun getX()</error> = 1
|
||||
@@ -630,6 +630,12 @@ public class JetPsiCheckerTestGenerated extends AbstractJetPsiCheckerTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelMultifileRuntime.kt")
|
||||
public void testTopLevelMultifileRuntime() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/duplicateJvmSignature/functionAndProperty/topLevelMultifileRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("trait.kt")
|
||||
public void testTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/duplicateJvmSignature/functionAndProperty/trait.kt");
|
||||
|
||||
Reference in New Issue
Block a user