Multi-module diagnostic tests supported

Test added for internal visibility
This commit is contained in:
Andrey Breslav
2014-05-16 14:59:04 +04:00
parent 236f38a26b
commit 9983a567d4
4 changed files with 200 additions and 22 deletions
@@ -0,0 +1,35 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// MODULE: m1
// FILE: a.kt
package p
public class A {
val a = A()
var v = A()
fun a() = A()
inner class B
}
val a = A()
var v = A()
fun a() = A()
class B
// MODULE: m2(m1)
// FILE: b.kt
import p.*
fun test() {
val _a = <!INVISIBLE_MEMBER!>a<!>
val _v = <!INVISIBLE_MEMBER!>v<!>
<!INVISIBLE_MEMBER!>a<!>()
<!INVISIBLE_MEMBER!>B<!>()
val inst = A()
val ia = inst.<!INVISIBLE_MEMBER!>a<!>
val iv = inst.<!INVISIBLE_MEMBER!>v<!>
inst.<!INVISIBLE_MEMBER!>a<!>()
inst.<!INVISIBLE_MEMBER!>B<!>()
}
@@ -21,25 +21,27 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.cli.jvm.compiler.CliLightClassGenerationSupport;
import org.jetbrains.jet.context.ContextPackage;
import org.jetbrains.jet.context.GlobalContext;
import org.jetbrains.jet.descriptors.serialization.descriptors.MemberFilter;
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
import org.jetbrains.jet.lang.descriptors.DependencyKind;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
import org.jetbrains.jet.lang.diagnostics.*;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.Diagnostics;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
@@ -47,27 +49,91 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
@Override
protected void analyzeAndCheck(File testDataFile, List<TestFile> testFiles) {
List<JetFile> jetFiles = getJetFiles(testFiles);
Map<TestModule, List<TestFile>> groupedByModule = KotlinPackage.groupByTo(
testFiles,
new LinkedHashMap<TestModule, List<TestFile>>(),
new Function1<TestFile, TestModule>() {
@Override
public TestModule invoke(TestFile file) {
return file.getModule();
}
}
);
CliLightClassGenerationSupport support = CliLightClassGenerationSupport.getInstanceForCli(getProject());
BindingTrace trace = support.getTrace();
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
getProject(), jetFiles, support.getTrace(),
Predicates.<PsiFile>alwaysTrue(), support.getModule(),
MemberFilter.ALWAYS_TRUE).getBindingContext();
List<JetFile> allJetFiles = new ArrayList<JetFile>();
Map<TestModule, ModuleDescriptorImpl> modules = createModules(groupedByModule);
for (Map.Entry<TestModule, List<TestFile>> entry : groupedByModule.entrySet()) {
TestModule testModule = entry.getKey();
List<? extends TestFile> testFilesInModule = entry.getValue();
List<JetFile> jetFiles = getJetFiles(testFilesInModule);
allJetFiles.addAll(jetFiles);
ModuleDescriptorImpl module = modules.get(testModule);
analyzeModule(trace, module == null ? support.getModule() : module, jetFiles);
}
boolean ok = true;
StringBuilder actualText = new StringBuilder();
for (TestFile testFile : testFiles) {
ok &= testFile.getActualText(bindingContext, actualText);
ok &= testFile.getActualText(trace.getBindingContext(), actualText);
}
JetTestUtils.assertEqualsToFile(testDataFile, actualText.toString());
assertTrue("Diagnostics mismatch. See the output above", ok);
checkAllResolvedCallsAreCompleted(jetFiles, bindingContext);
checkAllResolvedCallsAreCompleted(allJetFiles, trace.getBindingContext());
}
private Map<TestModule, ModuleDescriptorImpl> createModules(Map<TestModule, List<TestFile>> groupedByModule) {
Map<TestModule, ModuleDescriptorImpl> modules = new HashMap<TestModule, ModuleDescriptorImpl>();
for (TestModule testModule : groupedByModule.keySet()) {
if (testModule == null) continue;
ModuleDescriptorImpl module = AnalyzerFacadeForJVM.createJavaModule("<" + testModule.getName() + ">");
modules.put(testModule, module);
}
for (TestModule testModule : groupedByModule.keySet()) {
if (testModule == null) continue;
ModuleDescriptorImpl module = modules.get(testModule);
for (TestModule dependency : testModule.getDependencies()) {
// Adding other modules as BINARIES here, because in teh reduced dependency ordering model they are equal to binaries
module.addFragmentProvider(DependencyKind.BINARIES, modules.get(dependency).getPackageFragmentProvider());
}
}
return modules;
}
private void analyzeModule(BindingTrace trace, ModuleDescriptorImpl module, List<JetFile> jetFiles) {
GlobalContext globalContext = ContextPackage.GlobalContext();
TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
globalContext.getStorageManager(),
globalContext.getExceptionTracker(),
Predicates.<PsiFile>alwaysTrue(),
false,
false
);
// New JavaDescriptorResolver is created for each module, which is good because it emulates different Java libraries for each module,
// albeit with same class names
InjectorForTopDownAnalyzerForJvm
injector = new InjectorForTopDownAnalyzerForJvm(getProject(), topDownAnalysisParameters, trace, module,
MemberFilter.ALWAYS_TRUE);
try {
module.addFragmentProvider(DependencyKind.BINARIES, injector.getJavaDescriptorResolver().getPackageFragmentProvider());
injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, jetFiles);
}
finally {
injector.destroy();
}
}
private static void checkAllResolvedCallsAreCompleted(@NotNull List<JetFile> jetFiles, @NotNull BindingContext bindingContext) {
@@ -29,6 +29,8 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.ConfigurationKind;
@@ -45,9 +47,7 @@ import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -107,17 +107,54 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture {
String expectedText = JetTestUtils.doLoadFile(file);
class ModuleAndDependencies {
final TestModule module;
final List<String> dependencies;
ModuleAndDependencies(TestModule module, List<String> dependencies) {
this.module = module;
this.dependencies = dependencies;
}
}
final Map<String, ModuleAndDependencies> modules = new HashMap<String, ModuleAndDependencies>();
List<TestFile> testFiles =
JetTestUtils.createTestFiles(file.getName(), expectedText, new JetTestUtils.TestFileFactory<TestFile>() {
JetTestUtils.createTestFiles(file.getName(), expectedText, new JetTestUtils.TestFileFactory<TestModule, TestFile>() {
@Override
public TestFile create(String fileName, String text, Map<String, String> directives) {
public TestFile createFile(@Nullable TestModule module, String fileName, String text, Map<String, String> directives) {
if (fileName.endsWith(".java")) {
writeJavaFile(fileName, text, javaFilesDir);
}
return new TestFile(fileName, text, directives);
return new TestFile(module, fileName, text, directives);
}
@Override
public TestModule createModule(String name, List<String> dependencies) {
TestModule module = new TestModule(name);
ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies));
assert oldValue == null : "Module " + name + " declared more than once";
return module;
}
});
for (final ModuleAndDependencies moduleAndDependencies : modules.values()) {
List<TestModule> dependencies = KotlinPackage.map(
moduleAndDependencies.dependencies,
new Function1<String, TestModule>() {
@Override
public TestModule invoke(String name) {
ModuleAndDependencies dependency = modules.get(name);
assert dependency != null : "Dependency not found: " + name + " for module " + moduleAndDependencies.module.getName();
return dependency.module;
}
}
);
moduleAndDependencies.module.getDependencies().addAll(dependencies);
}
analyzeAndCheck(file, testFiles);
}
@@ -126,7 +163,7 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture {
List<TestFile> files
);
protected static List<JetFile> getJetFiles(List<TestFile> testFiles) {
protected static List<JetFile> getJetFiles(List<? extends TestFile> testFiles) {
List<JetFile> jetFiles = Lists.newArrayList();
for (TestFile testFile : testFiles) {
if (testFile.getJetFile() != null) {
@@ -202,19 +239,41 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture {
});
}
protected static class TestModule {
private final String name;
private final List<TestModule> dependencies = new ArrayList<TestModule>();
public TestModule(@NotNull String name) {
this.name = name;
}
@NotNull
public String getName() {
return name;
}
@NotNull
public List<TestModule> getDependencies() {
return dependencies;
}
}
protected class TestFile {
private final List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
private final String expectedText;
private final TestModule module;
private final String clearText;
private final JetFile jetFile;
private final Condition<Diagnostic> whatDiagnosticsToConsider;
private final boolean declareCheckType;
public TestFile(
@Nullable TestModule module,
String fileName,
String textWithMarkers,
Map<String, String> directives
) {
this.module = module;
this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives);
this.declareCheckType = directives.containsKey(CHECK_TYPE_DIRECTIVE);
if (fileName.endsWith(".java")) {
@@ -234,6 +293,10 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture {
}
}
@Nullable
public TestModule getModule() {
return module;
}
@Nullable
public JetFile getJetFile() {
@@ -33,7 +33,7 @@ import org.jetbrains.jet.checkers.AbstractJetDiagnosticsTest;
@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class, JetDiagnosticsTestGenerated.TailRecursion.class})
public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
@TestMetadata("compiler/testData/diagnostics/tests")
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.CyclicHierarchy.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.Imports.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NamedArguments.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Typedefs.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class})
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.CyclicHierarchy.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.Imports.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.Multimodule.class, Tests.NamedArguments.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Typedefs.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class})
public static class Tests extends AbstractJetDiagnosticsTest {
@TestMetadata("Abstract.kt")
public void testAbstract() throws Exception {
@@ -4861,6 +4861,19 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
}
@TestMetadata("compiler/testData/diagnostics/tests/multimodule")
public static class Multimodule extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInMultimodule() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/multimodule"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("internal.kt")
public void testInternal() throws Exception {
doTest("compiler/testData/diagnostics/tests/multimodule/internal.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/namedArguments")
public static class NamedArguments extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInNamedArguments() throws Exception {
@@ -7251,6 +7264,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
suite.addTestSuite(J_k.class);
suite.addTest(Jdk_annotations.innerSuite());
suite.addTestSuite(Library.class);
suite.addTestSuite(Multimodule.class);
suite.addTestSuite(NamedArguments.class);
suite.addTestSuite(NullabilityAndAutoCasts.class);
suite.addTestSuite(NullableTypes.class);