Fix visibility checker for import.
This commit is contained in:
@@ -117,14 +117,14 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
|||||||
importDirective: JetImportDirective,
|
importDirective: JetImportDirective,
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
shouldBeVisibleFrom: DeclarationDescriptor // todo
|
packageFragmentForVisibilityCheck: PackageFragmentDescriptor?
|
||||||
): JetScope {
|
): JetScope {
|
||||||
val importedReference = importDirective.importedReference ?: return JetScope.Empty
|
val importedReference = importDirective.importedReference ?: return JetScope.Empty
|
||||||
val path = importedReference.asQualifierPartList(trace)
|
val path = importedReference.asQualifierPartList(trace)
|
||||||
val lastPart = path.lastOrNull() ?: return JetScope.Empty
|
val lastPart = path.lastOrNull() ?: return JetScope.Empty
|
||||||
|
|
||||||
if (importDirective.isAllUnder) {
|
if (importDirective.isAllUnder) {
|
||||||
val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, shouldBeVisibleFrom,
|
val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForVisibilityCheck,
|
||||||
scopeForFirstPart = null, inImport = true) ?: return JetScope.Empty
|
scopeForFirstPart = null, inImport = true) ?: return JetScope.Empty
|
||||||
if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) {
|
if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) {
|
||||||
trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star
|
trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star
|
||||||
@@ -136,12 +136,12 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
|||||||
else {
|
else {
|
||||||
val aliasName = JetPsiUtil.getAliasName(importDirective)
|
val aliasName = JetPsiUtil.getAliasName(importDirective)
|
||||||
if (aliasName == null) { // import kotlin.
|
if (aliasName == null) { // import kotlin.
|
||||||
resolveToPackageOrClass(path, moduleDescriptor, trace, shouldBeVisibleFrom, scopeForFirstPart = null, inImport = true)
|
resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForVisibilityCheck, scopeForFirstPart = null, inImport = true)
|
||||||
return JetScope.Empty
|
return JetScope.Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
val packageOrClassDescriptor = resolveToPackageOrClass(path.subList(0, path.size() - 1), moduleDescriptor,
|
val packageOrClassDescriptor = resolveToPackageOrClass(path.subList(0, path.size() - 1), moduleDescriptor,
|
||||||
trace, shouldBeVisibleFrom, scopeForFirstPart = null, inImport = true)
|
trace, packageFragmentForVisibilityCheck, scopeForFirstPart = null, inImport = true)
|
||||||
?: return JetScope.Empty
|
?: return JetScope.Empty
|
||||||
val descriptors = SmartList<DeclarationDescriptor>()
|
val descriptors = SmartList<DeclarationDescriptor>()
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
|||||||
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
|
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
|
||||||
}
|
}
|
||||||
if (descriptors.isNotEmpty()) {
|
if (descriptors.isNotEmpty()) {
|
||||||
storageResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom, inImport = true, isQualifier = false)
|
storageResult(trace, lastPart.expression, descriptors, packageFragmentForVisibilityCheck, inImport = true, isQualifier = false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
|
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
|
||||||
@@ -249,7 +249,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
|||||||
path: List<QualifierPart>,
|
path: List<QualifierPart>,
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
shouldBeVisibleFrom: DeclarationDescriptor,
|
shouldBeVisibleFrom: DeclarationDescriptor?,
|
||||||
scopeForFirstPart: LexicalScope?,
|
scopeForFirstPart: LexicalScope?,
|
||||||
inImport: Boolean
|
inImport: Boolean
|
||||||
): DeclarationDescriptor? {
|
): DeclarationDescriptor? {
|
||||||
|
|||||||
@@ -60,10 +60,13 @@ public class FileScopeProviderImpl(
|
|||||||
val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.getPackageFqName())
|
val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.getPackageFqName())
|
||||||
.sure { "Could not find fragment ${file.getPackageFqName()} for file ${file.getName()}" }
|
.sure { "Could not find fragment ${file.getPackageFqName()} for file ${file.getName()}" }
|
||||||
|
|
||||||
val aliasImportResolver = LazyImportResolver(storageManager, qualifiedExpressionResolver, this, moduleDescriptor, AliasImportsIndexed(imports), bindingTrace)
|
fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace)
|
||||||
val allUnderImportResolver = LazyImportResolver(storageManager, qualifiedExpressionResolver, this, moduleDescriptor, AllUnderImportsIndexed(imports), bindingTrace)
|
= LazyImportResolver(storageManager, qualifiedExpressionResolver, this, moduleDescriptor, indexedImports, trace, packageFragment)
|
||||||
val defaultAliasImportResolver = LazyImportResolver(storageManager, qualifiedExpressionResolver, this, moduleDescriptor, AliasImportsIndexed(defaultImports), tempTrace)
|
|
||||||
val defaultAllUnderImportResolver = LazyImportResolver(storageManager, qualifiedExpressionResolver, this, moduleDescriptor, AllUnderImportsIndexed(defaultImports), tempTrace)
|
val aliasImportResolver = createImportResolver(AliasImportsIndexed(imports), bindingTrace)
|
||||||
|
val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace)
|
||||||
|
val defaultAliasImportResolver = createImportResolver(AliasImportsIndexed(defaultImports), tempTrace)
|
||||||
|
val defaultAllUnderImportResolver = createImportResolver(AllUnderImportsIndexed(defaultImports), tempTrace)
|
||||||
|
|
||||||
val scopeChain = ArrayList<JetScope>()
|
val scopeChain = ArrayList<JetScope>()
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ class LazyImportResolver(
|
|||||||
val fileScopeProvider: FileScopeProvider,
|
val fileScopeProvider: FileScopeProvider,
|
||||||
val moduleDescriptor: ModuleDescriptor,
|
val moduleDescriptor: ModuleDescriptor,
|
||||||
val indexedImports: IndexedImports,
|
val indexedImports: IndexedImports,
|
||||||
private val traceForImportResolve: BindingTrace
|
private val traceForImportResolve: BindingTrace,
|
||||||
|
private val packageFragment: PackageFragmentDescriptor
|
||||||
) {
|
) {
|
||||||
private val importedScopesProvider = storageManager.createMemoizedFunction {
|
private val importedScopesProvider = storageManager.createMemoizedFunction {
|
||||||
directive: JetImportDirective -> ImportDirectiveResolveCache(directive)
|
directive: JetImportDirective -> ImportDirectiveResolveCache(directive)
|
||||||
@@ -99,9 +100,8 @@ class LazyImportResolver(
|
|||||||
directiveUnderResolve = directive
|
directiveUnderResolve = directive
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// todo use packageViewFragment for visibility
|
|
||||||
val directiveImportScope = qualifiedExpressionResolver.processImportReference(
|
val directiveImportScope = qualifiedExpressionResolver.processImportReference(
|
||||||
directive, moduleDescriptor, traceForImportResolve, moduleDescriptor)
|
directive, moduleDescriptor, traceForImportResolve, packageFragment)
|
||||||
val descriptors = if (directive.isAllUnder()) emptyList() else directiveImportScope.getAllDescriptors()
|
val descriptors = if (directive.isAllUnder()) emptyList() else directiveImportScope.getAllDescriptors()
|
||||||
|
|
||||||
PlatformTypesMappedToKotlinChecker.checkPlatformTypesMappedToKotlin(moduleDescriptor, traceForImportResolve, directive, descriptors)
|
PlatformTypesMappedToKotlinChecker.checkPlatformTypesMappedToKotlin(moduleDescriptor, traceForImportResolve, directive, descriptors)
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// FILE: j/JavaPublic.java
|
||||||
|
package j;
|
||||||
|
|
||||||
|
public class JavaPublic {
|
||||||
|
public static void javaM() {}
|
||||||
|
public static int javaP = 4;
|
||||||
|
static int javaPackageLocal = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: j/JavaPackageLocal.java
|
||||||
|
package j;
|
||||||
|
|
||||||
|
class JavaPackageLocal {
|
||||||
|
static void javaMPackage() {}
|
||||||
|
static int javaPPackage = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: j/JavaProtected.java
|
||||||
|
package j;
|
||||||
|
|
||||||
|
public class JavaProtected {
|
||||||
|
protected static void javaMProtected() {}
|
||||||
|
protected static int javaPProtected = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: j/JavaPrivate.java
|
||||||
|
package j;
|
||||||
|
|
||||||
|
public class JavaPrivate {
|
||||||
|
private static void javaMPrivate() {}
|
||||||
|
private static int javaPPrivate = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: k1.kt
|
||||||
|
package k
|
||||||
|
|
||||||
|
import j.JavaPublic
|
||||||
|
import j.JavaPublic.javaM
|
||||||
|
import j.JavaPublic.javaP
|
||||||
|
import j.JavaPublic.<!INVISIBLE_REFERENCE!>javaPackageLocal<!>
|
||||||
|
|
||||||
|
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>
|
||||||
|
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>.<!INVISIBLE_REFERENCE!>javaMPackage<!>
|
||||||
|
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>.<!INVISIBLE_REFERENCE!>javaPPackage<!>
|
||||||
|
|
||||||
|
import j.JavaProtected
|
||||||
|
import j.JavaProtected.javaMProtected
|
||||||
|
import j.JavaProtected.javaPProtected
|
||||||
|
|
||||||
|
import j.JavaPrivate
|
||||||
|
import j.JavaPrivate.<!INVISIBLE_REFERENCE!>javaMPrivate<!>
|
||||||
|
import j.JavaPrivate.<!INVISIBLE_REFERENCE!>javaPPrivate<!>
|
||||||
|
|
||||||
|
// FILE: k2.kt
|
||||||
|
package j
|
||||||
|
|
||||||
|
import j.JavaPublic
|
||||||
|
import j.JavaPublic.javaM
|
||||||
|
import j.JavaPublic.javaP
|
||||||
|
import j.JavaPublic.javaPackageLocal
|
||||||
|
|
||||||
|
import j.JavaPackageLocal
|
||||||
|
import j.JavaPackageLocal.javaMPackage
|
||||||
|
import j.JavaPackageLocal.javaPPackage
|
||||||
|
|
||||||
|
import j.JavaProtected
|
||||||
|
import j.JavaProtected.javaMProtected
|
||||||
|
import j.JavaProtected.javaPProtected
|
||||||
|
|
||||||
|
import j.JavaPrivate
|
||||||
|
import j.JavaPrivate.<!INVISIBLE_REFERENCE!>javaMPrivate<!>
|
||||||
|
import j.JavaPrivate.<!INVISIBLE_REFERENCE!>javaPPrivate<!>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
package j {
|
||||||
|
|
||||||
|
public/*package*/ open class JavaPackageLocal {
|
||||||
|
public/*package*/ constructor JavaPackageLocal()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public/*package*/ final var javaPPackage: kotlin.Int
|
||||||
|
public/*package*/ open fun javaMPackage(): kotlin.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class JavaPrivate {
|
||||||
|
public constructor JavaPrivate()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
private final var javaPPrivate: kotlin.Int
|
||||||
|
private open fun javaMPrivate(): kotlin.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class JavaProtected {
|
||||||
|
public constructor JavaProtected()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
protected/*protected static*/ final var javaPProtected: kotlin.Int
|
||||||
|
protected/*protected static*/ open fun javaMProtected(): kotlin.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class JavaPublic {
|
||||||
|
public constructor JavaPublic()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public final var javaP: kotlin.Int
|
||||||
|
public/*package*/ final var javaPackageLocal: kotlin.Int
|
||||||
|
public open fun javaM(): kotlin.Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package k {
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// MODULE: m1
|
||||||
|
// FILE: k1.kt
|
||||||
|
package k
|
||||||
|
|
||||||
|
private class KPrivate
|
||||||
|
internal class KInternal
|
||||||
|
public class KPublic
|
||||||
|
|
||||||
|
class A {
|
||||||
|
protected class KProtected
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: k2.kt
|
||||||
|
package k2
|
||||||
|
|
||||||
|
import k.<!INVISIBLE_REFERENCE!>KPrivate<!>
|
||||||
|
import k.KInternal
|
||||||
|
import k.KPublic
|
||||||
|
import k.A.KProtected
|
||||||
|
|
||||||
|
// MODULE: m2(m1)
|
||||||
|
// FILE: k3.kt
|
||||||
|
package k3
|
||||||
|
|
||||||
|
import k.<!INVISIBLE_REFERENCE!>KPrivate<!>
|
||||||
|
import k.<!INVISIBLE_REFERENCE!>KInternal<!>
|
||||||
|
import k.KPublic
|
||||||
|
import k.A.KProtected
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// -- Module: <m1> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package k {
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
protected final class KProtected {
|
||||||
|
public constructor KProtected()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal final class KInternal {
|
||||||
|
public constructor KInternal()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class KPrivate {
|
||||||
|
public constructor KPrivate()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class KPublic {
|
||||||
|
public constructor KPublic()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package k2 {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m2> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package k {
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
// -- Module: <m1> --
|
||||||
|
}
|
||||||
|
|
||||||
|
internal final class KInternal {
|
||||||
|
// -- Module: <m1> --
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class KPrivate {
|
||||||
|
// -- Module: <m1> --
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class KPublic {
|
||||||
|
// -- Module: <m1> --
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package k2 {
|
||||||
|
}
|
||||||
|
|
||||||
|
package k3 {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -6537,6 +6537,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("CheckJavaVisibility.kt")
|
||||||
|
public void testCheckJavaVisibility() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/CheckJavaVisibility.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("CheckVisibility.kt")
|
||||||
|
public void testCheckVisibility() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/CheckVisibility.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ClassClash.kt")
|
@TestMetadata("ClassClash.kt")
|
||||||
public void testClassClash() throws Exception {
|
public void testClassClash() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ClassClash.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ClassClash.kt");
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public fun JetElement.analyzeFullyAndGetResult(vararg extraFiles: JetFile): Anal
|
|||||||
return KotlinCacheService.getInstance(getProject()).getResolutionFacade(listOf(this) + extraFiles.toList()).analyzeFullyAndGetResult(listOf(this))
|
return KotlinCacheService.getInstance(getProject()).getResolutionFacade(listOf(this) + extraFiles.toList()).analyzeFullyAndGetResult(listOf(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this method don't check visibility and collect all descriptors with given fqName
|
||||||
public fun ResolutionFacade.resolveImportReference(
|
public fun ResolutionFacade.resolveImportReference(
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
fqName: FqName
|
fqName: FqName
|
||||||
@@ -81,7 +82,7 @@ public fun ResolutionFacade.resolveImportReference(
|
|||||||
val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false))
|
val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false))
|
||||||
val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java)
|
val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java)
|
||||||
return qualifiedExpressionResolver.processImportReference(
|
return qualifiedExpressionResolver.processImportReference(
|
||||||
importDirective, moduleDescriptor, BindingTraceContext(), moduleDescriptor).getAllDescriptors()
|
importDirective, moduleDescriptor, BindingTraceContext(), packageFragmentForVisibilityCheck = null).getAllDescriptors()
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: idea default API returns module search scope for file under module but not in source or production source (for example, test data )
|
//NOTE: idea default API returns module search scope for file under module but not in source or production source (for example, test data )
|
||||||
|
|||||||
Reference in New Issue
Block a user