Support JS-targeted diagnostic tests
This commit is contained in:
@@ -19,6 +19,6 @@
|
|||||||
<orderEntry type="module" module-name="serialization.java" />
|
<orderEntry type="module" module-name="serialization.java" />
|
||||||
<orderEntry type="module" module-name="util" />
|
<orderEntry type="module" module-name="util" />
|
||||||
<orderEntry type="module" module-name="builtins-serializer" />
|
<orderEntry type="module" module-name="builtins-serializer" />
|
||||||
|
<orderEntry type="module" module-name="js.frontend" scope="TEST" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ public class JetTestUtils {
|
|||||||
*
|
*
|
||||||
* Several files may follow one module
|
* Several files may follow one module
|
||||||
*/
|
*/
|
||||||
public static final Pattern FILE_OR_MODULE_PATTERN = Pattern.compile("(?://\\s*MODULE:\\s*(\\w+)(\\(\\w+(?:, \\w+)*\\))?\\s*)?" +
|
public static final Pattern FILE_OR_MODULE_PATTERN = Pattern.compile("(?://\\s*MODULE(?:\\[(\\w+)\\])?:\\s*(\\w+)(\\(\\w+(?:, \\w+)*\\))?\\s*)?" +
|
||||||
"//\\s*FILE:\\s*(.*)$", Pattern.MULTILINE);
|
"//\\s*FILE:\\s*(.*)$", Pattern.MULTILINE);
|
||||||
public static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*!(\\w+)(:\\s*(.*)$)?", Pattern.MULTILINE);
|
public static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*!(\\w+)(:\\s*(.*)$)?", Pattern.MULTILINE);
|
||||||
|
|
||||||
@@ -502,7 +502,7 @@ public class JetTestUtils {
|
|||||||
|
|
||||||
public interface TestFileFactory<M, F> {
|
public interface TestFileFactory<M, F> {
|
||||||
F createFile(@Nullable M module, @NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives);
|
F createFile(@Nullable M module, @NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives);
|
||||||
M createModule(@NotNull String name, @NotNull List<String> dependencies);
|
M createModule(@NotNull String name, @Nullable String platform, @NotNull List<String> dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class TestFileFactoryNoModules<F> implements TestFileFactory<Void, F> {
|
public static abstract class TestFileFactoryNoModules<F> implements TestFileFactory<Void, F> {
|
||||||
@@ -520,7 +520,7 @@ public class JetTestUtils {
|
|||||||
public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives);
|
public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void createModule(@NotNull String name, @NotNull List<String> dependencies) {
|
public Void createModule(@NotNull String name, @Nullable String platform, @NotNull List<String> dependencies) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,13 +540,14 @@ public class JetTestUtils {
|
|||||||
M module = null;
|
M module = null;
|
||||||
// Many files
|
// Many files
|
||||||
while (true) {
|
while (true) {
|
||||||
String moduleName = matcher.group(1);
|
String platform = matcher.group(1);
|
||||||
String moduleDependencies = matcher.group(2);
|
String moduleName = matcher.group(2);
|
||||||
|
String moduleDependencies = matcher.group(3);
|
||||||
if (moduleName != null) {
|
if (moduleName != null) {
|
||||||
module = factory.createModule(moduleName, parseDependencies(moduleDependencies));
|
module = factory.createModule(moduleName, platform, parseDependencies(moduleDependencies));
|
||||||
}
|
}
|
||||||
|
|
||||||
String fileName = matcher.group(3);
|
String fileName = matcher.group(4);
|
||||||
int start = processedChars;
|
int start = processedChars;
|
||||||
|
|
||||||
boolean nextFileExists = matcher.find();
|
boolean nextFileExists = matcher.find();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiClass;
|
|||||||
import com.intellij.psi.impl.compiled.ClsElementImpl;
|
import com.intellij.psi.impl.compiled.ClsElementImpl;
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.checkers.KotlinMultiFileTestWithWithJava;
|
import org.jetbrains.jet.checkers.KotlinMultiFileTestWithWithJava;
|
||||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||||
@@ -76,7 +77,7 @@ public abstract class AbstractKotlinLightClassTest extends KotlinMultiFileTestWi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void createTestModule(String name) {
|
protected Void createTestModule(@NotNull String name, @Nullable String platform) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ import org.jetbrains.jet.storage.LockBasedStorageManager;
|
|||||||
import org.jetbrains.jet.test.util.DescriptorValidator;
|
import org.jetbrains.jet.test.util.DescriptorValidator;
|
||||||
import org.jetbrains.jet.test.util.RecursiveDescriptorComparator;
|
import org.jetbrains.jet.test.util.RecursiveDescriptorComparator;
|
||||||
import org.jetbrains.jet.utils.UtilsPackage;
|
import org.jetbrains.jet.utils.UtilsPackage;
|
||||||
|
import org.jetbrains.k2js.analyze.TopDownAnalyzerFacadeForJS;
|
||||||
|
import org.jetbrains.k2js.config.Config;
|
||||||
|
import org.jetbrains.k2js.config.EcmaVersion;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -114,8 +117,6 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
|
|||||||
module.seal();
|
module.seal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// New JavaDescriptorResolver is created for each module, which is good because it emulates different Java libraries for each module,
|
|
||||||
// albeit with same class names
|
|
||||||
ExceptionTracker tracker = new ExceptionTracker();
|
ExceptionTracker tracker = new ExceptionTracker();
|
||||||
GlobalContext context = new SimpleGlobalContext(
|
GlobalContext context = new SimpleGlobalContext(
|
||||||
new LoggingStorageManager(
|
new LoggingStorageManager(
|
||||||
@@ -124,17 +125,7 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
|
|||||||
),
|
),
|
||||||
tracker
|
tracker
|
||||||
);
|
);
|
||||||
|
analyzeModuleContents(context, jetFiles, module, moduleTrace, testModule);
|
||||||
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
|
|
||||||
getProject(),
|
|
||||||
context,
|
|
||||||
jetFiles,
|
|
||||||
moduleTrace,
|
|
||||||
Predicates.<PsiFile>alwaysTrue(),
|
|
||||||
module,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
checkAllResolvedCallsAreCompleted(jetFiles, moduleTrace.getBindingContext());
|
checkAllResolvedCallsAreCompleted(jetFiles, moduleTrace.getBindingContext());
|
||||||
}
|
}
|
||||||
@@ -209,6 +200,49 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
|
|||||||
return new File(FileUtil.getNameWithoutExtension(testDataFile.getAbsolutePath()) + ".lazy.log");
|
return new File(FileUtil.getNameWithoutExtension(testDataFile.getAbsolutePath()) + ".lazy.log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void analyzeModuleContents(
|
||||||
|
GlobalContext context,
|
||||||
|
List<JetFile> jetFiles,
|
||||||
|
ModuleDescriptorImpl module,
|
||||||
|
BindingTrace moduleTrace,
|
||||||
|
TestModule testModule
|
||||||
|
) {
|
||||||
|
|
||||||
|
String platform = getPlatform(testModule);
|
||||||
|
if ("jvm".equals(platform)) {
|
||||||
|
// New JavaDescriptorResolver is created for each module, which is good because it emulates different Java libraries for each module,
|
||||||
|
// albeit with same class names
|
||||||
|
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
|
||||||
|
getProject(),
|
||||||
|
context,
|
||||||
|
jetFiles,
|
||||||
|
moduleTrace,
|
||||||
|
Predicates.<PsiFile>alwaysTrue(),
|
||||||
|
module,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ("js".equals(platform)) {
|
||||||
|
TopDownAnalyzerFacadeForJS.analyzeFilesWithGivenTrace(
|
||||||
|
jetFiles,
|
||||||
|
moduleTrace,
|
||||||
|
module,
|
||||||
|
Predicates.<PsiFile>alwaysTrue(),
|
||||||
|
new Config(getProject(), "module", EcmaVersion.v5, false, true) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected List<JetFile> generateLibFiles() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalStateException("Unknown platform in module " + testModule.getName() + ": " + platform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void validateAndCompareDescriptorWithFile(
|
private void validateAndCompareDescriptorWithFile(
|
||||||
File expectedFile,
|
File expectedFile,
|
||||||
List<TestFile> testFiles,
|
List<TestFile> testFiles,
|
||||||
@@ -281,12 +315,12 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
|
|||||||
return RECURSIVE.filterRecursion(stepIntoFilter).withValidationStrategy(DescriptorValidator.ValidationVisitor.errorTypesAllowed());
|
return RECURSIVE.filterRecursion(stepIntoFilter).withValidationStrategy(DescriptorValidator.ValidationVisitor.errorTypesAllowed());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<TestModule, ModuleDescriptorImpl> createModules(Map<TestModule, List<TestFile>> groupedByModule) {
|
private Map<TestModule, ModuleDescriptorImpl> createModules(Map<TestModule, List<TestFile>> groupedByModule) {
|
||||||
Map<TestModule, ModuleDescriptorImpl> modules = new HashMap<TestModule, ModuleDescriptorImpl>();
|
Map<TestModule, ModuleDescriptorImpl> modules = new HashMap<TestModule, ModuleDescriptorImpl>();
|
||||||
|
|
||||||
for (TestModule testModule : groupedByModule.keySet()) {
|
for (TestModule testModule : groupedByModule.keySet()) {
|
||||||
if (testModule == null) continue;
|
if (testModule == null) continue;
|
||||||
ModuleDescriptorImpl module = TopDownAnalyzerFacadeForJVM.createJavaModule("<" + testModule.getName() + ">");
|
ModuleDescriptorImpl module = createModule(testModule);
|
||||||
modules.put(testModule, module);
|
modules.put(testModule, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,6 +336,28 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
|
|||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ModuleDescriptorImpl createModule(TestModule testModule) {
|
||||||
|
String name = "<" + testModule.getName() + ">";
|
||||||
|
String platform = getPlatform(testModule);
|
||||||
|
if ("jvm".equals(platform)) {
|
||||||
|
return TopDownAnalyzerFacadeForJVM.createJavaModule(name);
|
||||||
|
}
|
||||||
|
else if ("js".equals(platform)) {
|
||||||
|
return TopDownAnalyzerFacadeForJS.createJsModule(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Unknown platform in module " + testModule.getName() + ": " + platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static String getPlatform(@Nullable TestModule testModule) {
|
||||||
|
if (testModule == null) return "jvm";
|
||||||
|
|
||||||
|
String platform = testModule.getPlatform();
|
||||||
|
if (platform == null) return "jvm";
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
private static void checkAllResolvedCallsAreCompleted(@NotNull List<JetFile> jetFiles, @NotNull BindingContext bindingContext) {
|
private static void checkAllResolvedCallsAreCompleted(@NotNull List<JetFile> jetFiles, @NotNull BindingContext bindingContext) {
|
||||||
for (JetFile file : jetFiles) {
|
for (JetFile file : jetFiles) {
|
||||||
if (!AnalyzingUtils.getSyntaxErrorRanges(file).isEmpty()) {
|
if (!AnalyzingUtils.getSyntaxErrorRanges(file).isEmpty()) {
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ public abstract class BaseDiagnosticsTest extends
|
|||||||
public static final boolean CHECK_LAZY_LOG_DEFAULT = "true".equals(System.getProperty("check.lazy.logs", "false"));
|
public static final boolean CHECK_LAZY_LOG_DEFAULT = "true".equals(System.getProperty("check.lazy.logs", "false"));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TestModule createTestModule(String name) {
|
protected TestModule createTestModule(@NotNull String name, @Nullable String platform) {
|
||||||
return new TestModule(name);
|
return new TestModule(name, platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -208,10 +208,12 @@ public abstract class BaseDiagnosticsTest extends
|
|||||||
|
|
||||||
protected static class TestModule implements Comparable<TestModule> {
|
protected static class TestModule implements Comparable<TestModule> {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final String platform;
|
||||||
private final List<TestModule> dependencies = new ArrayList<TestModule>();
|
private final List<TestModule> dependencies = new ArrayList<TestModule>();
|
||||||
|
|
||||||
public TestModule(@NotNull String name) {
|
public TestModule(@NotNull String name, @Nullable String platform) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.platform = platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -219,6 +221,11 @@ public abstract class BaseDiagnosticsTest extends
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getPlatform() {
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<TestModule> getDependencies() {
|
public List<TestModule> getDependencies() {
|
||||||
return dependencies;
|
return dependencies;
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ public abstract class KotlinMultiFileTestWithWithJava<M, F> extends JetLiteFixtu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public M createModule(@NotNull String name, @NotNull List<String> dependencies) {
|
public M createModule(@NotNull String name, @Nullable String platform, @NotNull List<String> dependencies) {
|
||||||
M module = createTestModule(name);
|
M module = createTestModule(name, platform);
|
||||||
ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies));
|
ModuleAndDependencies oldValue = modules.put(name, new ModuleAndDependencies(module, dependencies));
|
||||||
assert oldValue == null : "Module " + name + " declared more than once";
|
assert oldValue == null : "Module " + name + " declared more than once";
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ public abstract class KotlinMultiFileTestWithWithJava<M, F> extends JetLiteFixtu
|
|||||||
doMultiFileTest(file, modules, testFiles);
|
doMultiFileTest(file, modules, testFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract M createTestModule(String name);
|
protected abstract M createTestModule(@NotNull String name, @Nullable String platform);
|
||||||
|
|
||||||
protected abstract F createTestFile(M module, String fileName, String text, Map<String, String> directives);
|
protected abstract F createTestFile(M module, String fileName, String text, Map<String, String> directives);
|
||||||
|
|
||||||
|
|||||||
@@ -63,9 +63,32 @@ public final class TopDownAnalyzerFacadeForJS {
|
|||||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||||
@NotNull Config config
|
@NotNull Config config
|
||||||
) {
|
) {
|
||||||
Project project = config.getProject();
|
BindingContext libraryContext = config.getLibraryContext();
|
||||||
|
BindingTrace trace = libraryContext == null
|
||||||
|
? new BindingTraceContext()
|
||||||
|
: new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library");
|
||||||
|
|
||||||
ModuleDescriptorImpl owner = createJsModule("<module>");
|
ModuleDescriptorImpl module = createJsModule("<module>");
|
||||||
|
module.addDependencyOnModule(module);
|
||||||
|
module.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
|
||||||
|
ModuleDescriptor libraryModule = config.getLibraryModule();
|
||||||
|
if (libraryModule != null) {
|
||||||
|
module.addDependencyOnModule((ModuleDescriptorImpl) libraryModule); // "import" analyzed library module
|
||||||
|
}
|
||||||
|
module.seal();
|
||||||
|
|
||||||
|
return analyzeFilesWithGivenTrace(files, trace, module, filesToAnalyzeCompletely, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static AnalysisResult analyzeFilesWithGivenTrace(
|
||||||
|
@NotNull Collection<JetFile> files,
|
||||||
|
@NotNull BindingTrace trace,
|
||||||
|
@NotNull ModuleDescriptorImpl module,
|
||||||
|
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||||
|
@NotNull Config config
|
||||||
|
) {
|
||||||
|
Project project = config.getProject();
|
||||||
|
|
||||||
Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely);
|
Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely);
|
||||||
|
|
||||||
@@ -73,25 +96,13 @@ public final class TopDownAnalyzerFacadeForJS {
|
|||||||
TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
|
TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
|
||||||
globalContext.getStorageManager(), globalContext.getExceptionTracker(), completely, false, false);
|
globalContext.getStorageManager(), globalContext.getExceptionTracker(), completely, false, false);
|
||||||
|
|
||||||
owner.addDependencyOnModule(owner);
|
InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, module);
|
||||||
owner.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
|
|
||||||
ModuleDescriptor libraryModule = config.getLibraryModule();
|
|
||||||
if (libraryModule != null) {
|
|
||||||
owner.addDependencyOnModule((ModuleDescriptorImpl) libraryModule); // "import" analyzed library module
|
|
||||||
}
|
|
||||||
owner.seal();
|
|
||||||
|
|
||||||
BindingContext libraryContext = config.getLibraryContext();
|
|
||||||
BindingTrace trace = libraryContext == null
|
|
||||||
? new BindingTraceContext()
|
|
||||||
: new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library");
|
|
||||||
InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner);
|
|
||||||
try {
|
try {
|
||||||
Collection<JetFile> allFiles = libraryModule != null ?
|
Collection<JetFile> allFiles = config.getLibraryModule() != null ?
|
||||||
files :
|
files :
|
||||||
Config.withJsLibAdded(files, config);
|
Config.withJsLibAdded(files, config);
|
||||||
injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, allFiles);
|
injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, allFiles);
|
||||||
return AnalysisResult.success(trace.getBindingContext(), owner);
|
return AnalysisResult.success(trace.getBindingContext(), module);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
injector.destroy();
|
injector.destroy();
|
||||||
@@ -118,7 +129,7 @@ public final class TopDownAnalyzerFacadeForJS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static ModuleDescriptorImpl createJsModule(@NotNull String name) {
|
public static ModuleDescriptorImpl createJsModule(@NotNull String name) {
|
||||||
return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, PlatformToKotlinClassMap.EMPTY);
|
return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, PlatformToKotlinClassMap.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user