separate compiler and plugin tests

This commit is contained in:
Dmitry Jemerov
2011-10-20 16:19:02 +02:00
parent a80398098b
commit ec6dec0d37
586 changed files with 69 additions and 42 deletions
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="IDEA 10.x" jdkType="IDEA JDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="backend" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="stdlib" />
</component>
</module>
@@ -0,0 +1,16 @@
package org.jetbrains.jet;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
/**
* @author yole
*/
public class JetLightProjectDescriptor extends DefaultLightProjectDescriptor {
public static JetLightProjectDescriptor INSTANCE = new JetLightProjectDescriptor();
@Override
public Sdk getSdk() {
return JetTestCaseBase.jdkFromIdeaHome();
}
}
@@ -0,0 +1,191 @@
package org.jetbrains.jet;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderFactoryImpl;
import com.intellij.mock.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.options.SchemesManagerFactory;
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiCachedValuesFactory;
import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.testFramework.MockSchemesManagerFactory;
import com.intellij.testFramework.PlatformLiteFixture;
import com.intellij.testFramework.TestDataFile;
import com.intellij.util.CachedValuesManagerImpl;
import com.intellij.util.Function;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusFactory;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.PicoInitializationException;
import org.picocontainer.PicoIntrospectionException;
import org.picocontainer.defaults.AbstractComponentAdapter;
import java.io.File;
import java.io.IOException;
/**
* @author abreslav
*/
public abstract class JetLiteFixture extends PlatformLiteFixture {
protected String myFileExt;
@NonNls
protected final String myFullDataPath;
protected PsiFile myFile;
private MockPsiManager myPsiManager;
private PsiFileFactoryImpl myFileFactory;
protected Language myLanguage;
protected final ParserDefinition[] myDefinitions;
public JetLiteFixture(@NonNls String dataPath) {
myFileExt = "jet";
myFullDataPath = getTestDataPath() + "/" + dataPath;
myDefinitions = new ParserDefinition[] {new JetParserDefinition()};
}
protected String getTestDataPath() {
return JetTestCaseBase.getTestDataPathBase();
}
@Override
protected void setUp() throws Exception {
super.setUp();
initApplication();
getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter("com.intellij.openapi.progress.ProgressManager", Object.class) {
@Override
public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException {
return new ProgressManagerImpl(getApplication());
}
@Override
public void verify(PicoContainer container) throws PicoIntrospectionException {
}
});
Extensions.registerAreaClass("IDEA_PROJECT", null);
myProject = disposeOnTearDown(new MockProjectEx(getTestRootDisposable()));
myPsiManager = new MockPsiManager(myProject);
myFileFactory = new PsiFileFactoryImpl(myPsiManager);
final MutablePicoContainer appContainer = getApplication().getPicoContainer();
registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication()));
registerComponentInstance(appContainer, SchemesManagerFactory.class, new MockSchemesManagerFactory());
final MockEditorFactory editorFactory = new MockEditorFactory();
registerComponentInstance(appContainer, EditorFactory.class, editorFactory);
registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function<CharSequence, Document>() {
@Override
public Document fun(CharSequence charSequence) {
return editorFactory.createDocument(charSequence);
}
}, FileDocumentManagerImpl.DOCUMENT_KEY));
registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager());
myLanguage = myLanguage == null && myDefinitions != null && myDefinitions.length > 0
? myDefinitions[0].getFileNodeType().getLanguage()
: myLanguage;
registerComponentInstance(appContainer, FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt)));
registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl());
registerApplicationService(DefaultASTFactory.class, new DefaultASTFactoryImpl());
registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl());
myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager)));
myProject.registerService(PsiManager.class, myPsiManager);
myProject.registerService(StartupManager.class, new StartupManagerImpl(myProject));
myProject.registerService(PsiFileFactory.class, new PsiFileFactoryImpl(myPsiManager));
registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class);
for (ParserDefinition definition : myDefinitions) {
addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition);
}
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
myFile = null;
myProject = null;
myPsiManager = null;
}
protected String loadFile(@NonNls @TestDataFile String name) throws IOException {
return doLoadFile(myFullDataPath, name);
}
protected static String doLoadFile(String myFullDataPath, String name) throws IOException {
String fullName = myFullDataPath + File.separatorChar + name;
String text = FileUtil.loadFile(new File(fullName), CharsetToolkit.UTF8).trim();
text = StringUtil.convertLineSeparators(text);
return text;
}
protected PsiFile createPsiFile(String name, String text) {
return createFile(name + "." + myFileExt, text);
}
protected PsiFile createFile(@NonNls String name, String text) {
LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text);
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false);
}
protected static void ensureParsed(PsiFile file) {
file.accept(new PsiElementVisitor() {
@Override
public void visitElement(PsiElement element) {
element.acceptChildren(this);
}
});
}
protected <T> void registerApplicationService(final Class<T> aClass, T object) {
getApplication().registerService(aClass, object);
Disposer.register(myProject, new Disposable() {
@Override
public void dispose() {
getApplication().getPicoContainer().unregisterComponent(aClass.getName());
}
});
}
protected <T> void addExplicitExtension(final LanguageExtension<T> instance, final Language language, final T object) {
instance.addExplicitExtension(language, object);
Disposer.register(myProject, new Disposable() {
@Override
public void dispose() {
instance.removeExplicitExtension(language, object);
}
});
}
protected void prepareForTest(String name) throws IOException {
String text = loadFile(name + "." + myFileExt);
createAndCheckPsiFile(name, text);
}
protected void createAndCheckPsiFile(String name, String text) {
myFile = createPsiFile(name, text);
ensureParsed(myFile);
assertEquals("light virtual file text mismatch", text, ((LightVirtualFile) myFile.getVirtualFile()).getContent().toString());
assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile()));
assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText());
assertEquals("psi text mismatch", text, myFile.getText());
}
}
@@ -0,0 +1,117 @@
package org.jetbrains.jet;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase {
private boolean checkInfos = false;
private String dataPath;
protected final String name;
public JetTestCaseBase(String dataPath, String name) {
this.dataPath = dataPath;
this.name = name;
}
public final JetTestCaseBase setCheckInfos(boolean checkInfos) {
this.checkInfos = checkInfos;
return this;
}
public static Sdk jdkFromIdeaHome() {
return new JavaSdkImpl().createJdk("JDK", "compiler/testData/mockJDK-1.7/jre", true);
}
@Override
protected String getTestDataPath() {
return getTestDataPathBase();
}
public static String getTestDataPathBase() {
return getHomeDirectory() + "/compiler/testData";
}
public static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetTestCaseBase.class, "/org/jetbrains/jet/JetTestCaseBase.class")).getParentFile().getParentFile().getParent();
}
@Override
protected Sdk getProjectJDK() {
return jdkFromIdeaHome();
}
@Override
public String getName() {
return "test" + name;
}
@Override
protected void runTest() throws Throwable {
doTest(getTestFilePath(), true, checkInfos);
}
@NotNull
protected String getTestFilePath() {
return dataPath + File.separator + name + ".jet";
}
protected String getDataPath() {
return dataPath;
}
public interface NamedTestFactory {
@NotNull Test createTest(@NotNull String dataPath, @NotNull String name);
}
@NotNull
public static TestSuite suiteForDirectory(String baseDataDir, @NotNull final String dataPath, boolean recursive, @NotNull NamedTestFactory factory) {
TestSuite suite = new TestSuite(dataPath);
final String extension = ".jet";
FilenameFilter extensionFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(extension);
}
};
File dir = new File(baseDataDir + dataPath);
FileFilter dirFilter = new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
};
if (recursive) {
File[] files = dir.listFiles(dirFilter);
assert files != null : dir;
List<File> subdirs = Arrays.asList(files);
Collections.sort(subdirs);
for (File subdir : subdirs) {
suite.addTest(suiteForDirectory(baseDataDir, dataPath + "/" + subdir.getName(), recursive, factory));
}
}
List<File> files = Arrays.asList(dir.listFiles(extensionFilter));
Collections.sort(files);
for (File file : files) {
String fileName = file.getName();
assert fileName != null;
suite.addTest(factory.createTest(dataPath, fileName.substring(0, fileName.length() - extension.length())));
}
return suite;
}
}
@@ -0,0 +1,96 @@
package org.jetbrains.jet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnostic;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.util.Collection;
/**
* @author abreslav
*/
public class JetTestUtils {
public static final BindingTrace DUMMY_TRACE = new BindingTrace() {
@Override
public BindingContext getBindingContext() {
return new BindingContext() {
@Override
public Collection<Diagnostic> getDiagnostics() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
return DUMMY_TRACE.get(slice, key);
}
};
}
@Override
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
}
@Override
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE;
return null;
}
@Override
public void report(@NotNull Diagnostic diagnostic) {
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic) diagnostic;
throw new IllegalStateException("Unresolved: " + unresolvedReferenceDiagnostic.getPsiElement().getText());
}
}
};
public static BindingTrace DUMMY_EXCEPTION_ON_ERROR_TRACE = new BindingTrace() {
@Override
public BindingContext getBindingContext() {
return new BindingContext() {
@Override
public Collection<Diagnostic> getDiagnostics() {
throw new UnsupportedOperationException();
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
return DUMMY_EXCEPTION_ON_ERROR_TRACE.get(slice, key);
}
};
}
@Override
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
}
@Override
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
return null;
}
@Override
public void report(@NotNull Diagnostic diagnostic) {
if (diagnostic.getSeverity() == Severity.ERROR) {
throw new IllegalStateException(diagnostic.getMessage());
}
}
};
}
@@ -0,0 +1,178 @@
/*
* @author max
*/
package org.jetbrains.jet.cfg;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.cfg.pseudocode.JetPseudocodeTrace;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class JetControlFlowTest extends JetTestCaseBase {
static {
System.setProperty("idea.platform.prefix", "Idea");
}
public JetControlFlowTest(String dataPath, String name) {
super(dataPath, name);
}
@Override
protected void runTest() throws Throwable {
configureByFile(getTestFilePath());
JetFile file = (JetFile) getFile();
final Map<JetElement, Pseudocode> data = new LinkedHashMap<JetElement, Pseudocode>();
final JetPseudocodeTrace pseudocodeTrace = new JetPseudocodeTrace() {
@Override
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
data.put(element, pseudocode);
}
@Override
public void close() {
for (Pseudocode pseudocode : data.values()) {
pseudocode.postProcess();
}
}
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
}
@Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
}
};
AnalyzerFacade.analyzeNamespace(file.getRootNamespace(), new JetControlFlowDataTraceFactory() {
@NotNull
@Override
public JetPseudocodeTrace createTrace(JetElement element) {
return pseudocodeTrace;
}
});
try {
processCFData(name, data);
}
catch (IOException e) {
throw new RuntimeException(e);
}
finally {
if ("true".equals(System.getProperty("jet.control.flow.test.dump.graphs"))) {
dumpDot(name, data.values());
}
}
}
private void processCFData(String name, Map<JetElement, Pseudocode> data) throws IOException {
Collection<Pseudocode> pseudocodes = data.values();
StringBuilder instructionDump = new StringBuilder();
int i = 0;
for (Pseudocode pseudocode : pseudocodes) {
JetElement correspondingElement = pseudocode.getCorrespondingElement();
String label;
if (correspondingElement instanceof JetNamedDeclaration) {
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) correspondingElement;
label = namedDeclaration.getName();
}
else {
label = "anonymous_" + i++;
}
instructionDump.append("== ").append(label).append(" ==\n");
instructionDump.append(correspondingElement.getText());
instructionDump.append("\n---------------------\n");
pseudocode.dumpInstructions(instructionDump);
instructionDump.append("=====================\n");
}
String expectedInstructionsFileName = getTestDataPath() + "/" + getTestFilePath().replace(".jet", ".instructions");
File expectedInstructionsFile = new File(expectedInstructionsFileName);
if (!expectedInstructionsFile.exists()) {
FileUtil.writeToFile(expectedInstructionsFile, instructionDump.toString());
fail("No expected instructions for " + name + " generated result is written into " + expectedInstructionsFileName);
}
String expectedInstructions = StringUtil.convertLineSeparators(FileUtil.loadFile(expectedInstructionsFile));
assertEquals(expectedInstructions, instructionDump.toString());
// StringBuilder graphDump = new StringBuilder();
// for (Pseudocode pseudocode : pseudocodes) {
// topOrderDump(pseudocode.)
// }
}
private void dumpDot(String name, Collection<Pseudocode> pseudocodes) throws FileNotFoundException {
String graphFileName = getTestDataPath() + "/" + getTestFilePath().replace(".jet", ".dot");
File target = new File(graphFileName);
PrintStream out = new PrintStream(target);
out.println("digraph " + name + " {");
int[] count = new int[1];
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
for (Pseudocode pseudocode : pseudocodes) {
pseudocode.dumpNodes(out, count, nodeToName);
}
int i = 0;
for (Pseudocode pseudocode : pseudocodes) {
String label;
JetElement correspondingElement = pseudocode.getCorrespondingElement();
if (correspondingElement instanceof JetNamedDeclaration) {
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) correspondingElement;
label = namedDeclaration.getName();
}
else {
label = "anonymous_" + i;
}
out.println("subgraph cluster_" + i + " {\n" +
"label=\"" + label + "\";\n" +
"color=blue;\n");
pseudocode.dumpEdges(out, count, nodeToName);
out.println("}");
i++;
}
out.println("}");
out.close();
}
public static TestSuite suite() {
TestSuite suite = new TestSuite();
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/cfg/", true, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetControlFlowTest(dataPath, name);
}
}));
return suite;
}
}
@@ -0,0 +1,125 @@
package org.jetbrains.jet.checkers;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiFile;
import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
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.ImportingStrategy;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public class CheckerTestUtilTest extends JetLiteFixture {
public CheckerTestUtilTest() {
super("checkerWithErrorTypes/checkerTestUtil");
}
protected void doTest(TheTest theTest) throws Exception {
prepareForTest("test");
theTest.test(myFile);
}
public void testEquals() throws Exception {
doTest(new TheTest() {
@Override
protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
}
});
}
public void testMissing() throws Exception {
doTest(new TheTest("Missing TYPE_MISMATCH at 56 to 57") {
@Override
protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
diagnostics.remove(0);
}
});
}
public void testUnexpected() throws Exception {
doTest(new TheTest("Unexpected TYPE_MISMATCH at 56 to 57") {
@Override
protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
diagnosedRanges.remove(0);
}
});
}
public void testBoth() throws Exception {
doTest(new TheTest("Unexpected TYPE_MISMATCH at 56 to 57", "Missing UNRESOLVED_REFERENCE at 166 to 168") {
@Override
protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
diagnosedRanges.remove(0);
diagnostics.remove(diagnostics.size() - 1);
}
});
}
public void testMissingInTheMiddle() throws Exception {
doTest(new TheTest("Unexpected NONE_APPLICABLE at 122 to 123", "Missing TYPE_MISMATCH at 161 to 169") {
@Override
protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
diagnosedRanges.remove(2);
diagnostics.remove(diagnostics.size() - 3);
}
});
}
private static abstract class TheTest {
private final String[] expected;
protected TheTest(String... expectedMessages) {
this.expected = expectedMessages;
}
public void test(PsiFile psiFile) {
BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache((JetFile) psiFile);
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
List<Diagnostic> diagnostics = Lists.newArrayList(bindingContext.getDiagnostics());
Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
makeTestData(diagnostics, diagnosedRanges);
final List<String> expectedMessages = Lists.newArrayList(expected);
final List<String> actualMessages = Lists.newArrayList();
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override
public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
String message = "Missing " + type + " at " + expectedStart + " to " + expectedEnd;
actualMessages.add(message);
}
@Override
public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) {
String message = "Unexpected " + type + " at " + actualStart + " to " + actualEnd;
actualMessages.add(message);
}
});
assertEquals(listToString(expectedMessages), listToString(actualMessages));
}
private String listToString(List<String> expectedMessages) {
StringBuilder stringBuilder = new StringBuilder();
for (String expectedMessage : expectedMessages) {
stringBuilder.append(expectedMessage).append("\n");
}
return stringBuilder.toString();
}
protected abstract void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges);
}
}
@@ -0,0 +1,118 @@
package org.jetbrains.jet.checkers;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import junit.framework.Test;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;
/**
* @author abreslav
*/
public class FullJetPsiCheckerTest extends JetTestCaseBase {
public FullJetPsiCheckerTest(@NonNls String dataPath, String name) {
super(dataPath, name);
}
@Override
public void runTest() throws Exception {
String fileName = name + ".jet";
String fullPath = getTestDataPath() + getTestFilePath();
String expectedText = loadFile(fullPath);
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
configureFromFileText(fileName, clearText);
JetFile jetFile = (JetFile) myFile;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(jetFile);
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override
public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
String message = "Missing " + type + DiagnosticUtils.atLocation(myFile, new TextRange(expectedStart, expectedEnd));
System.err.println(message);
}
@Override
public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) {
String message = "Unexpected " + type + DiagnosticUtils.atLocation(myFile, new TextRange(actualStart, actualEnd));
System.err.println(message);
}
});
String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString();
assertEquals(expectedText, actualText);
// String myFullDataPath = getTestDataPath() + getDataPath();
// System.out.println("myFullDataPath = " + myFullDataPath);
// convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath));
}
private String loadFile(String fullPath) throws IOException {
final File ioFile = new File(fullPath);
String fileText = FileUtil.loadFile(ioFile, CharsetToolkit.UTF8);
return StringUtil.convertLineSeparators(fileText);
}
private void convert(File src, File dest) throws IOException {
File[] files = src.listFiles();
for (File file : files) {
try {
if (file.isDirectory()) {
File destDir = new File(dest, file.getName());
destDir.mkdir();
convert(file, destDir);
continue;
}
if (!file.getName().endsWith(".jet")) continue;
String text = loadFile(file.getAbsolutePath());
Pattern pattern = Pattern.compile("</?(error|warning|info( descr=\"[\\w ]+\")?)>");
String clearText = pattern.matcher(text).replaceAll("");
configureFromFileText(file.getName(), clearText);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) myFile);
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(myFile, bindingContext).toString();
File destFile = new File(dest, file.getName());
FileWriter fileWriter = new FileWriter(destFile);
fileWriter.write(expectedText);
fileWriter.close();
}
catch (RuntimeException e) {
e.printStackTrace();
}
}
}
public static Test suite() {
return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/full/", true, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new FullJetPsiCheckerTest(dataPath, name);
}
});
}
}
@@ -0,0 +1,42 @@
package org.jetbrains.jet.checkers;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase;
/**
* @author abreslav
*/
public class JetPsiCheckerTest extends JetTestCaseBase {
public JetPsiCheckerTest(String dataPath, String name) {
super(dataPath, name);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/regression/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/infos/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name).setCheckInfos(true);
}
}));
return suite;
}
}
@@ -0,0 +1,104 @@
package org.jetbrains.jet.checkers;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.TextRange;
import junit.framework.Test;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
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.ImportingStrategy;
import java.util.List;
/**
* @author abreslav
*/
public class QuickJetPsiCheckerTest extends JetLiteFixture {
private String name;
public QuickJetPsiCheckerTest(@NonNls String dataPath, String name) {
super(dataPath);
this.name = name;
}
@Override
public String getName() {
return "test" + name;
}
@Override
public void runTest() throws Exception {
String expectedText = loadFile(name + ".jet");
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
createAndCheckPsiFile(name, clearText);
JetFile jetFile = (JetFile) myFile;
BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache(jetFile);
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override
public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
String message = "Missing " + type + DiagnosticUtils.atLocation(myFile, new TextRange(expectedStart, expectedEnd));
System.err.println(message);
}
@Override
public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) {
String message = "Unexpected " + type + DiagnosticUtils.atLocation(myFile, new TextRange(actualStart, actualEnd));
System.err.println(message);
}
});
String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString();
assertEquals(expectedText, actualText);
// convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath));
}
// private void convert(File src, File dest) throws IOException {
// File[] files = src.listFiles();
// for (File file : files) {
// try {
// if (file.isDirectory()) {
// File destDir = new File(dest, file.getName());
// destDir.mkdir();
// convert(file, destDir);
// continue;
// }
// if (!file.getName().endsWith(".jet")) continue;
// String text = doLoadFile(file.getParentFile().getAbsolutePath(), file.getName());
// Pattern pattern = Pattern.compile("</?(error|warning)>");
// String clearText = pattern.matcher(text).replaceAll("");
// createAndCheckPsiFile(name, clearText);
//
// BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache((JetFile) myFile);
// String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(myFile, bindingContext).toString();
//
// File destFile = new File(dest, file.getName());
// FileWriter fileWriter = new FileWriter(destFile);
// fileWriter.write(expectedText);
// fileWriter.close();
// }
// catch (RuntimeException e) {
// e.printStackTrace();
// }
// }
// }
public static Test suite() {
return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/quick", true, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new QuickJetPsiCheckerTest(dataPath, name);
}
});
}
}
@@ -0,0 +1,99 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Method;
public class ArrayGenTest extends CodegenTestCase {
public void testKt238 () throws Exception {
blackBoxFile("regressions/kt238.jet");
}
public void testKt326 () throws Exception {
blackBoxFile("regressions/kt326.jet");
System.out.println(generateToText());
}
public void testCreateMultiInt () throws Exception {
loadText("fun foo() = Array<Array<Int>> (5, { Array<Int>(it, {239}) })");
Method foo = generateFunction();
Integer[][] invoke = (Integer[][]) foo.invoke(null);
assertEquals(invoke[2].length, 2);
assertEquals(invoke[4].length, 4);
assertEquals(invoke[4][2].intValue(), 239);
}
public void testCreateMultiIntNullable () throws Exception {
loadText("fun foo() = Array<Array<Int?>> (5, { Array<Int?>(it) })");
Method foo = generateFunction();
Integer[][] invoke = (Integer[][]) foo.invoke(null);
assertEquals(invoke[2].length, 2);
assertEquals(invoke[4].length, 4);
}
public void testCreateMultiString () throws Exception {
loadText("fun foo() = Array<Array<String>> (5, { Array<String>(0,{\"\"}) })");
Method foo = generateFunction();
Object invoke = foo.invoke(null);
System.out.println(invoke.getClass());
assertTrue(invoke instanceof Object[]);
}
public void testCreateMultiGenerics () throws Exception {
loadText("class L<T>() { val a = Array<T>(5) } fun foo() = L<Int>.a");
System.out.println(generateToText());
Method foo = generateFunction();
Object invoke = foo.invoke(null);
System.out.println(invoke.getClass());
assertTrue(invoke instanceof Integer[]);
}
public void testIntGenerics () throws Exception {
loadText("class L<T>(var a : T) {} fun foo() = L<Int>(5).a");
System.out.println(generateToText());
Method foo = generateFunction();
Object invoke = foo.invoke(null);
System.out.println(invoke.getClass());
assertTrue(invoke instanceof Integer);
}
public void testIterator () throws Exception {
loadText("fun box() { val x = Array<Int>(5, { it } ).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testPrimitiveIterator () throws Exception {
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testLongIterator () throws Exception {
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testCharIterator () throws Exception {
loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testArrayIndices () throws Exception {
loadText("fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testCharIndices () throws Exception {
loadText("fun box() { val x = CharArray(5).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.codegen;
public class BridgeMethodGenTest extends CodegenTestCase {
public void testBridgeMethod () throws Exception {
blackBoxFile("bridge.jet");
}
}
@@ -0,0 +1,199 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
/**
* @author yole
*/
public class ClassGenTest extends CodegenTestCase {
public void testPSVMClass() throws Exception {
loadFile("classes/simpleClass.jet");
final Class aClass = loadClass("SimpleClass", generateClassesInFile());
final Method[] methods = aClass.getDeclaredMethods();
// public int SimpleClass.foo()
// public jet.typeinfo.TypeInfo SimpleClass.getTypeInfo()
assertEquals(2, methods.length);
}
public void testArrayListInheritance() throws Exception {
loadFile("classes/inheritingFromArrayList.jet");
final Class aClass = loadClass("Foo", generateClassesInFile());
checkInterface(aClass, List.class);
}
public void testInheritanceAndDelegation_DelegatingDefaultConstructorProperties() throws Exception {
blackBoxFile("classes/inheritance.jet");
}
public void testFunDelegation() throws Exception {
blackBoxFile("classes/funDelegation.jet");
}
public void testPropertyDelegation() throws Exception {
blackBoxFile("classes/propertyDelegation.jet");
}
public void testDiamondInheritance() throws Exception {
blackBoxFile("classes/diamondInheritance.jet");
}
public void testRightHandOverride() throws Exception {
blackBoxFile("classes/rightHandOverride.jet");
}
private static void checkInterface(Class aClass, Class ifs) {
for (Class anInterface : aClass.getInterfaces()) {
if (anInterface == ifs) return;
}
fail(aClass.getName() + " must have " + ifs.getName() + " in its interfaces");
}
public void testNewInstanceExplicitConstructor() throws Exception {
loadFile("classes/newInstanceDefaultConstructor.jet");
System.out.println(generateToText());
final Method method = generateFunction("test");
final Integer returnValue = (Integer) method.invoke(null);
assertEquals(610, returnValue.intValue());
}
public void testInnerClass() throws Exception {
blackBoxFile("classes/innerClass.jet");
}
public void testInheritedInnerClass() throws Exception {
blackBoxFile("classes/inheritedInnerClass.jet");
}
public void testInitializerBlock() throws Exception {
blackBoxFile("classes/initializerBlock.jet");
}
public void testAbstractMethod() throws Exception {
loadText("abstract class Foo { abstract fun x(): String; fun y(): Int = 0 }");
final ClassFileFactory codegens = generateClassesInFile();
final Class aClass = loadClass("Foo", codegens);
assertNotNull(aClass.getMethod("x"));
assertNotNull(findMethodByName(aClass, "y"));
}
public void testInheritedMethod() throws Exception {
blackBoxFile("classes/inheritedMethod.jet");
}
public void testInitializerBlockDImpl() throws Exception {
blackBoxFile("classes/initializerBlockDImpl.jet");
}
public void testPropertyInInitializer() throws Exception {
blackBoxFile("classes/propertyInInitializer.jet");
}
public void testOuterThis() throws Exception {
blackBoxFile("classes/outerThis.jet");
}
public void testSecondaryConstructors() throws Exception {
blackBoxFile("classes/secondaryConstructors.jet");
}
public void testExceptionConstructor() throws Exception {
blackBoxFile("classes/exceptionConstructor.jet");
}
public void testSimpleBox() throws Exception {
blackBoxFile("classes/simpleBox.jet");
}
public void testAbstractClass() throws Exception {
loadText("abstract class SimpleClass() { }");
final Class aClass = loadAllClasses(generateClassesInFile()).get("SimpleClass");
assertTrue((aClass.getModifiers() & Modifier.ABSTRACT) != 0);
}
public void testClassObject() throws Exception {
blackBoxFile("classes/classObject.jet");
}
public void testClassObjectMethod() throws Exception {
blackBoxFile("classes/classObjectMethod.jet");
}
public void testClassObjectInterface() throws Exception {
loadFile("classes/classObjectInterface.jet");
final Method method = generateFunction();
Object result = method.invoke(null);
assertInstanceOf(result, Runnable.class);
}
public void testOverloadBinaryOperator() throws Exception {
blackBoxFile("classes/overloadBinaryOperator.jet");
}
public void testOverloadUnaryOperator() throws Exception {
blackBoxFile("classes/overloadUnaryOperator.jet");
}
public void testOverloadPlusAssign() throws Exception {
blackBoxFile("classes/overloadPlusAssign.jet");
}
public void testOverloadPlusAssignReturn() throws Exception {
blackBoxFile("classes/overloadPlusAssignReturn.jet");
}
public void testOverloadPlusToPlusAssign() throws Exception {
blackBoxFile("classes/overloadPlusToPlusAssign.jet");
}
public void testEnumClass() throws Exception {
loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }");
final Class direction = loadAllClasses(generateClassesInFile()).get("Direction");
System.out.println(generateToText());
final Field north = direction.getField("NORTH");
assertEquals(direction, north.getType());
assertInstanceOf(north.get(null), direction);
}
public void testEnumConstantConstructors() throws Exception {
loadText("enum class Color(val rgb: Int) { RED: Color(0xFF0000); GREEN: Color(0x00FF00); }");
final Class colorClass = loadAllClasses(generateClassesInFile()).get("Color");
final Field redField = colorClass.getField("RED");
final Object redValue = redField.get(null);
final Method rgbMethod = colorClass.getMethod("getRgb");
assertEquals(0xFF0000, rgbMethod.invoke(redValue));
}
public void testKt249() throws Exception {
blackBoxFile("regressions/kt249.jet");
}
public void testKt48 () throws Exception {
blackBoxFile("regressions/kt48.jet");
System.out.println(generateToText());
}
public void testKt309 () throws Exception {
loadText("fun box() = null");
final Method method = generateFunction("box");
assertEquals(method.getReturnType().getName(), "java.lang.Object");
System.out.println(generateToText());
}
public void testKt343 () throws Exception {
blackBoxFile("regressions/kt343.jet");
System.out.println(generateToText());
}
public void testKt344 () throws Exception {
loadFile("regressions/kt344.jet");
System.out.println(generateToText());
blackBox();
}
}
@@ -0,0 +1,40 @@
package org.jetbrains.jet.codegen;
/**
* @author max
*/
public class ClosuresGenTest extends CodegenTestCase {
public void testSimplestClosure() throws Exception {
blackBoxFile("classes/simplestClosure.jet");
System.out.println(generateToText());
}
public void testSimplestClosureAndBoxing() throws Exception {
blackBoxFile("classes/simplestClosureAndBoxing.jet");
}
public void testClosureWithParameter() throws Exception {
blackBoxFile("classes/closureWithParameter.jet");
}
public void testClosureWithParameterAndBoxing() throws Exception {
blackBoxFile("classes/closureWithParameterAndBoxing.jet");
}
public void testExtensionClosure() throws Exception {
blackBoxFile("classes/extensionClosure.jet");
}
public void testEnclosingLocalVariable() throws Exception {
blackBoxFile("classes/enclosingLocalVariable.jet");
System.out.println(generateToText());
}
public void testDoubleEnclosedLocalVariable() throws Exception {
blackBoxFile("classes/doubleEnclosedLocalVariable.jet");
}
public void testEnclosingThis() throws Exception {
blackBoxFile("classes/enclosingThis.jet");
}
}
@@ -0,0 +1,242 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetLightProjectDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.parsing.JetParsingTest;
import org.jetbrains.jet.plugin.JetFileType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author yole
*/
public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
private MyClassLoader myClassLoader;
protected static void assertThrows(Method foo, Class<? extends Throwable> exceptionClass, Object instance, Object... args) throws IllegalAccessException {
boolean caught = false;
try {
foo.invoke(instance, args);
}
catch(InvocationTargetException ex) {
caught = exceptionClass.isInstance(ex.getTargetException());
}
assertTrue(caught);
}
@Override
protected void setUp() throws Exception {
super.setUp();
myClassLoader = new MyClassLoader(NamespaceGenTest.class.getClassLoader());
}
@Override
protected void tearDown() throws Exception {
myClassLoader = null;
super.tearDown();
}
protected void loadText(final String text) {
myFixture.configureByText(JetFileType.INSTANCE, text);
}
protected void loadFile(final String name) {
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
}
protected void loadFile() {
loadFile(getPrefix() + "/" + getTestName(true) + ".jet");
}
protected String getPrefix() {
throw new UnsupportedOperationException();
}
protected void blackBoxFile(String filename) {
loadFile(filename);
String actual;
try {
actual = blackBox();
} catch (NoClassDefFoundError e) {
System.out.println(generateToText());
throw e;
} catch (Throwable e) {
System.out.println(generateToText());
throw new RuntimeException(e);
}
if (!"OK".equals(actual)) {
System.out.println(generateToText());
}
assertEquals("OK", actual);
}
protected String blackBox() throws Exception {
ClassFileFactory codegens = generateClassesInFile();
CodegensClassLoader loader = new CodegensClassLoader(codegens);
JetFile jetFile = (JetFile) myFixture.getFile();
final JetNamespace namespace = jetFile.getRootNamespace();
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
Class<?> namespaceClass = loader.loadClass(fqName);
Method method = namespaceClass.getMethod("box");
return (String) method.invoke(null);
}
protected String generateToText() {
GenerationState state = new GenerationState(getProject(), true);
JetFile jetFile = (JetFile) myFixture.getFile();
AnalyzingUtils.checkForSyntacticErrors(jetFile);
state.compile(jetFile);
StringBuilder answer = new StringBuilder();
final ClassFileFactory factory = state.getFactory();
List<String> files = factory.files();
for (String file : files) {
answer.append("@").append(file).append('\n');
answer.append(factory.asText(file));
}
return answer.toString();
}
protected Class generateNamespaceClass() {
ClassFileFactory state = generateClassesInFile();
return loadRootNamespaceClass(state);
}
protected Class loadRootNamespaceClass(ClassFileFactory state) {
JetFile jetFile = (JetFile) myFixture.getFile();
final JetNamespace namespace = jetFile.getRootNamespace();
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
Map<String, Class> classMap = loadAllClasses(state);
return classMap.get(fqName);
}
protected Class loadClass(String fqName, ClassFileFactory state) {
List<String> files = state.files();
for (String file : files) {
if (file.equals(fqName.replace('.', '/') + ".class")) {
final byte[] data = state.asBytes(file);
return myClassLoader.doDefineClass(fqName, data);
}
}
fail("No classfile was generated for: " + fqName);
return null;
}
protected Map<String, Class> loadAllClasses(ClassFileFactory state) {
Map<String, Class> result = new HashMap<String, Class>();
for (String fileName : state.files()) {
String className = StringUtil.trimEnd(fileName, ".class").replace('/', '.');
byte[] data = state.asBytes(fileName);
Class aClass = myClassLoader.doDefineClass(className, data);
result.put(className, aClass);
}
return result;
}
protected ClassFileFactory generateClassesInFile() {
try {
GenerationState state = new GenerationState(getProject(), false);
JetFile jetFile = (JetFile) myFixture.getFile();
AnalyzingUtils.checkForSyntacticErrors(jetFile);
state.compile(jetFile);
return state.getFactory();
} catch (RuntimeException e) {
System.out.println(generateToText());
throw e;
}
}
protected Method generateFunction() {
Class aClass = generateNamespaceClass();
try {
return aClass.getMethods()[0];
} catch (Error e) {
System.out.println(generateToText());
throw e;
}
}
protected Method generateFunction(String name) {
Class aClass = generateNamespaceClass();
final Method method = findMethodByName(aClass, name);
if (method == null) {
throw new IllegalArgumentException("couldn't find method " + name);
}
return method;
}
@Nullable
protected static Method findMethodByName(Class aClass, String name) {
for (Method method : aClass.getDeclaredMethods()) {
if (method.getName().equals(name)) {
return method;
}
}
return null;
}
protected static void assertIsCurrentTime(long returnValue) {
long currentTime = System.currentTimeMillis();
assertTrue(Math.abs(returnValue - currentTime) <= 1L);
}
protected Class loadImplementationClass(ClassFileFactory codegens, final String name) {
return loadClass(name, codegens);
}
private static class MyClassLoader extends ClassLoader {
public MyClassLoader(ClassLoader parent) {
super(parent);
}
public Class doDefineClass(String name, byte[] data) {
return defineClass(name, data, 0, data.length);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}
}
private static class CodegensClassLoader extends ClassLoader {
private final ClassFileFactory state;
public CodegensClassLoader(ClassFileFactory state) {
super(CodegenTestCase.class.getClassLoader());
this.state = state;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String file = name.replace('.', '/') + ".class";
if (state.files().contains(file)) {
byte[] bytes = state.asBytes(file);
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
}
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JetLightProjectDescriptor.INSTANCE;
}
}
@@ -0,0 +1,210 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
/**
* @author yole
*/
public class ControlStructuresTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "controlStructures";
}
public void testIf() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(15, main.invoke(null, true));
assertEquals(20, main.invoke(null, false));
}
public void testSingleBranchIf() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(15, main.invoke(null, true));
assertEquals(20, main.invoke(null, false));
}
public void testWhile() throws Exception {
factorialTest("controlStructures/while.jet");
}
public void testDoWhile() throws Exception {
factorialTest("controlStructures/doWhile.jet");
}
public void testBreak() throws Exception {
factorialTest("controlStructures/break.jet");
}
private void factorialTest(final String name) throws IllegalAccessException, InvocationTargetException {
loadFile(name);
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(6, main.invoke(null, 3));
assertEquals(120, main.invoke(null, 5));
}
public void testContinue() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(3, main.invoke(null, 4));
assertEquals(7, main.invoke(null, 5));
}
public void testIfNoElse() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(5, main.invoke(null, 5, true));
assertEquals(10, main.invoke(null, 5, false));
}
public void testCondJumpOnStack() throws Exception {
loadText("import java.lang.Boolean as jlBoolean; fun foo(a: String): Int = if (jlBoolean.parseBoolean(a)) 5 else 10");
final Method main = generateFunction();
assertEquals(5, main.invoke(null, "true"));
assertEquals(10, main.invoke(null, "false"));
}
public void testFor() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
List<String> args = Arrays.asList("IntelliJ", " ", "IDEA");
assertEquals("IntelliJ IDEA", main.invoke(null, args));
}
public void testIfBlock() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
List<String> args = Arrays.asList("IntelliJ", " ", "IDEA");
assertEquals("TTT", main.invoke(null, args));
args = Arrays.asList("JetBrains");
assertEquals("F", main.invoke(null, args));
}
public void testForInArray() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
String[] args = new String[] { "IntelliJ", " ", "IDEA" };
assertEquals("IntelliJ IDEA", main.invoke(null, new Object[] { args }));
}
public void testForInRange() throws Exception {
loadText("fun foo(sb: StringBuilder) { for(x in 1..4) sb.append(x) }");
final Method main = generateFunction();
StringBuilder stringBuilder = new StringBuilder();
main.invoke(null, stringBuilder);
assertEquals("1234", stringBuilder.toString());
}
public void testThrowCheckedException() throws Exception {
loadText("fun foo() { throw Exception(); }");
final Method main = generateFunction();
boolean caught = false;
try {
main.invoke(null);
} catch (InvocationTargetException e) {
if (e.getTargetException().getClass() == Exception.class) {
caught = true;
}
}
assertTrue(caught);
}
public void testTryCatch() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals("no message", main.invoke(null, "0"));
assertEquals("For input string: \"a\"", main.invoke(null, "a"));
}
public void testTryFinally() throws Exception {
loadFile();
System.out.println(generateToText());
final Method main = generateFunction();
StringBuilder sb = new StringBuilder();
main.invoke(null, sb, "9");
assertEquals("foo9bar", sb.toString());
sb = new StringBuilder();
boolean caught = false;
try {
main.invoke(null, sb, "x");
}
catch(InvocationTargetException e) {
caught = e.getTargetException() instanceof NumberFormatException;
}
assertTrue(caught);
assertEquals("foobar", sb.toString());
}
public void testForUserType() throws Exception {
blackBoxFile("controlStructures/forUserType.jet");
}
public void testForIntArray() throws Exception {
blackBoxFile("controlStructures/forIntArray.jet");
}
public void testForPrimitiveIntArray() throws Exception {
blackBoxFile("controlStructures/forPrimitiveIntArray.jet");
}
public void testForNullableIntArray() throws Exception {
blackBoxFile("controlStructures/forNullableIntArray.jet");
}
public void testForIntRange() {
blackBoxFile("controlStructures/forIntRange.jet");
}
public void testKt237() throws Exception {
blackBoxFile("regressions/kt237.jet");
}
public void testCompareToNull() throws Exception {
loadText("fun foo(a: String?, b: String?): Boolean = a == null && b !== null && null == a && null !== b");
String text = generateToText();
assertTrue(!text.contains("java/lang/Object.equals"));
System.out.println(text);
final Method main = generateFunction();
assertEquals(true, main.invoke(null, null, "lala"));
assertEquals(false, main.invoke(null, null, null));
}
public void testCompareToNonnullableEq() throws Exception {
loadText("fun foo(a: String?, b: String): Boolean = a == b || b == a");
String text = generateToText();
System.out.println(text);
final Method main = generateFunction();
assertEquals(false, main.invoke(null, null, "lala"));
assertEquals(true, main.invoke(null, "papa", "papa"));
}
public void testCompareToNonnullableNotEq() throws Exception {
loadText("fun foo(a: String?, b: String): Boolean = a != b");
String text = generateToText();
System.out.println(text);
assertTrue(text.contains("IXOR"));
final Method main = generateFunction();
assertEquals(true, main.invoke(null, null, "lala"));
assertEquals(false, main.invoke(null, "papa", "papa"));
}
public void testKt299() throws Exception {
blackBoxFile("regressions/kt299.jet");
}
}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Method;
/**
* @author yole
*/
public class ExtensionFunctionsTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "extensionFunctions";
}
public void testSimple() throws Exception {
loadFile();
final Method foo = generateFunction("foo");
final Character c = (Character) foo.invoke(null);
assertEquals('f', c.charValue());
}
public void testWhenFail() throws Exception {
loadFile();
Method foo = generateFunction("foo");
assertThrows(foo, Exception.class, null, new StringBuilder());
}
public void testGeneric() throws Exception {
blackBoxFile("extensionFunctions/generic.jet");
}
}
@@ -0,0 +1,16 @@
package org.jetbrains.jet.codegen;
/**
* @author alex.tkachman
*/
public class FunctionGenTest extends CodegenTestCase {
public void testDefaultArgs() throws Exception {
blackBoxFile("functions/defaultargs.jet");
System.out.println(generateToText());
}
public void testNoThisNoClosure() throws Exception {
blackBoxFile("functions/nothisnoclosure.jet");
System.out.println(generateToText());
}
}
@@ -0,0 +1,562 @@
package org.jetbrains.jet.codegen;
import jet.IntRange;
import jet.Tuple2;
import jet.Tuple3;
import jet.Tuple4;
import jet.typeinfo.TypeInfo;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author yole
*/
public class NamespaceGenTest extends CodegenTestCase {
public void testPSVM() throws Exception {
loadFile("PSVM.jet");
final String text = generateToText();
System.out.println(text);
final Method main = generateFunction();
Object[] args = new Object[] { new String[0] };
main.invoke(null, args);
}
public void testReturnOne() throws Exception {
loadText("fun f() : Int { return 42; }");
final String text = generateToText();
System.out.println(text);
final Method main = generateFunction();
final Object returnValue = main.invoke(null, new Object[0]);
assertEquals(new Integer(42), returnValue);
}
public void testReturnA() throws Exception {
loadText("fun foo(a : Int) = a");
final String text = generateToText();
System.out.println(text);
final Method main = generateFunction();
final Object returnValue = main.invoke(null, 50);
assertEquals(new Integer(50), returnValue);
}
public void testLocalProperty() throws Exception {
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/localProperty.jet");
final String text = generateToText();
System.out.println(text);
final Method main = generateFunction();
final Object returnValue = main.invoke(null, 76);
assertEquals(new Integer(50), returnValue);
}
public void testCurrentTime() throws Exception {
loadText("fun f() : Long { return System.currentTimeMillis(); }");
System.out.println(generateToText());
final Method main = generateFunction();
final long returnValue = (Long) main.invoke(null);
assertIsCurrentTime(returnValue);
}
public void testIdentityHashCode() throws Exception {
loadText("fun f(o: Any) : Int { return System.identityHashCode(o); }");
System.out.println(generateToText());
final Method main = generateFunction();
Object o = new Object();
final int returnValue = (Integer) main.invoke(null, o);
assertEquals(returnValue, System.identityHashCode(o));
}
public void testSystemOut() throws Exception {
loadFile("systemOut.jet");
final Method main = generateFunction();
final Object returnValue = main.invoke(null);
assertEquals(returnValue, System.out);
}
public void testHelloWorld() throws Exception {
loadFile("helloWorld.jet");
System.out.println(generateToText());
generateFunction(); // assert that it can be verified
}
public void testAssign() throws Exception {
loadFile("assign.jet");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(2, main.invoke(null));
}
public void testBoxedInt() throws Exception {
loadText("fun foo(a: Int?) = if (a != null) a else 239");
final Method main = generateFunction();
assertEquals(610, main.invoke(null, 610));
assertEquals(239, main.invoke(null, new Object[]{null}));
}
public void testIntBoxed() throws Exception {
loadText("fun foo(s: String): Int? = Integer.getInteger(s, 239)");
final Method main = generateFunction();
assertEquals(239, main.invoke(null, "no.such.system.property"));
}
public void testBoxConstant() throws Exception {
loadText("fun foo(): Int? = 239");
final Method main = generateFunction();
assertEquals(239, main.invoke(null));
}
public void testBoxVariable() throws Exception {
loadText("fun foo(): Int? { var x = 239; return x; }");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(239, main.invoke(null));
}
public void testAugAssign() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; x += 5; return x; }");
final Method main = generateFunction();
assertEquals(10, main.invoke(null, 5));
}
public void testBooleanNot() throws Exception {
loadText("fun foo(b: Boolean): Boolean = !b");
final Method main = generateFunction();
assertEquals(true, main.invoke(null, false));
assertEquals(false, main.invoke(null, true));
}
public void testBooleanNotJump() throws Exception {
loadText("fun foo(a: Int) : Int = if (!(a < 5)) a else 0");
final Method main = generateFunction();
assertEquals(6, main.invoke(null, 6));
assertEquals(0, main.invoke(null, 4));
}
public void testAnd() throws Exception {
loadText("fun foo(a : Int): Boolean = a > 0 && a/0 > 0");
final Method main = generateFunction();
assertEquals(false, main.invoke(null, 0));
boolean hadException = false;
try {
main.invoke(null, 5);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof ArithmeticException) {
hadException = true;
}
}
assertTrue(hadException);
}
public void testOr() throws Exception {
loadText("fun foo(a : Int): Boolean = a > 0 || a/0 > 0");
final Method main = generateFunction();
assertEquals(true, main.invoke(null, 5));
boolean hadException = false;
try {
main.invoke(null, 0);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof ArithmeticException) {
hadException = true;
}
}
assertTrue(hadException);
}
public void testBottles2() throws Exception {
loadFile("bottles2.jet");
System.out.println(generateToText());
final Method main = generateFunction();
main.invoke(null); // ensure no exception
}
public void testJavaConstructor() throws Exception {
loadText("fun foo(): StringBuilder = StringBuilder()");
System.out.println(generateToText());
final Method main = generateFunction();
final Object result = main.invoke(null);
assertTrue(result instanceof StringBuilder);
}
public void testJavaConstructorWithParameters() throws Exception {
loadText("fun foo(): StringBuilder = StringBuilder(\"beer\")");
final Method main = generateFunction();
final StringBuilder result = (StringBuilder) main.invoke(null);
assertEquals("beer", result.toString());
}
public void testJavaEquals() throws Exception {
loadText("fun foo(s1: String, s2: String) = s1 == s2");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(Boolean.TRUE, main.invoke(null, new String("jet"), new String("jet")));
assertEquals(Boolean.FALSE, main.invoke(null, new String("jet"), new String("ceylon")));
}
public void testJavaNotEquals() throws Exception {
loadText("fun foo(s1: String, s2: String) = s1 != s2");
final Method main = generateFunction();
assertEquals(Boolean.FALSE, main.invoke(null, new String("jet"), new String("jet")));
assertEquals(Boolean.TRUE, main.invoke(null, new String("jet"), new String("ceylon")));
}
public void testJavaEqualsNull() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 == s2");
final Method main = generateFunction();
System.out.println(generateToText());
assertEquals(Boolean.TRUE, main.invoke(null, null, null));
assertEquals(Boolean.FALSE, main.invoke(null, "jet", null));
assertEquals(Boolean.FALSE, main.invoke(null, null, "jet"));
}
public void testEqualsNullLiteral() throws Exception {
loadText("fun foo(s: String?) = s == null");
final Method main = generateFunction();
System.out.println(generateToText());
assertEquals(Boolean.TRUE, main.invoke(null, new Object[] { null }));
assertEquals(Boolean.FALSE, main.invoke(null, "jet"));
}
public void testTripleEq() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 === s2");
final Method main = generateFunction();
String s1 = new String("jet");
String s2 = new String("jet");
assertEquals(Boolean.TRUE, main.invoke(null, s1, s1));
assertEquals(Boolean.FALSE, main.invoke(null, s1, s2));
}
public void testTripleNotEq() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 !== s2");
final Method main = generateFunction();
String s1 = new String("jet");
String s2 = new String("jet");
assertEquals(Boolean.FALSE, main.invoke(null, s1, s1));
assertEquals(Boolean.TRUE, main.invoke(null, s1, s2));
}
public void testFunctionCall() throws Exception {
loadFile("functionCall.jet");
System.out.println(generateToText());
final Method main = generateFunction("f");
assertEquals("foo", main.invoke(null));
}
public void testStringPlus() throws Exception {
loadText("fun foo(s1: String, s2: String) = s1 + s2");
final Method main = generateFunction();
assertEquals("jetLang", main.invoke(null, "jet", "Lang"));
}
public void testStringPlusChained() throws Exception {
loadText("fun foo(s1: String, s2: String, s3: String) = s1 + s2 + s3");
final String text = generateToText();
final int firstStringBuilderCreation = text.indexOf("NEW java/lang/StringBuilder");
assertEquals(-1, text.indexOf("NEW java/lang/StringBuilder", firstStringBuilderCreation + 1));
final Method main = generateFunction();
assertEquals("jet Lang", main.invoke(null, "jet", " ", "Lang"));
}
public void testStringPlusEq() throws Exception {
loadText("fun foo(s: String) : String { val result = s; result += s; return result; } ");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals("JarJar", main.invoke(null, "Jar"));
}
public void testStringCompare() throws Exception {
loadText("fun foo(s1: String, s2: String) = s1 < s2");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(Boolean.TRUE, main.invoke(null, "Ceylon", "Java"));
assertEquals(Boolean.FALSE, main.invoke(null, "Jet", "Java"));
}
public void testElvis() throws Exception {
loadText("fun foo(s: String?) = s ?: \"null\"");
final Method main = generateFunction();
assertEquals("jet", main.invoke(null, "jet"));
assertEquals("null", main.invoke(null, new Object[] { null }));
}
public void testElvisInt() throws Exception {
loadText("fun foo(a: Int?): Int = a ?: 239");
final Method main = generateFunction();
assertEquals(610, main.invoke(null, 610));
assertEquals(239, main.invoke(null, new Object[]{null}));
}
public void _testVarargs() throws Exception {
loadText("fun foo() = java.util.Arrays.asList(\"IntelliJ\", \"IDEA\")");
final Method main = generateFunction();
ArrayList arrayList = (ArrayList) main.invoke(null);
}
public void testFieldRead() throws Exception {
loadText("import java.awt.*; fun foo(c: GridBagConstraints) = c.gridx");
System.out.println(generateToText());
final Method main = generateFunction();
GridBagConstraints c = new GridBagConstraints();
c.gridx = 239;
assertEquals(239, main.invoke(null, c));
}
public void testFieldWrite() throws Exception {
loadText("import java.awt.*; fun foo(c: GridBagConstraints) { c.gridx = 239 }");
final Method main = generateFunction();
GridBagConstraints c = new GridBagConstraints();
main.invoke(null, c);
assertEquals(239, c.gridx);
}
public void testFieldIncrement() throws Exception {
loadText("import java.awt.*; fun foo(c: GridBagConstraints) { c.gridx++; return; }");
System.out.println(generateToText());
final Method main = generateFunction();
GridBagConstraints c = new GridBagConstraints();
c.gridx = 609;
main.invoke(null, c);
assertEquals(610, c.gridx);
}
public void testFieldAugAssign() throws Exception {
loadText("import java.awt.*; fun foo(c: GridBagConstraints) { c.gridx *= 2; return; }");
System.out.println(generateToText());
final Method main = generateFunction();
GridBagConstraints c = new GridBagConstraints();
c.gridx = 305;
main.invoke(null, c);
assertEquals(610, c.gridx);
}
public void testIncrementAsLastOperation() throws Exception {
loadText("fun foo() { var a = 0; a++; }");
generateFunction(); // make sure we're not falling off end of code
}
public void testArrayRead() throws Exception {
loadText("fun foo(c: Array<String>) = c[0]");
final Method main = generateFunction();
assertEquals("main", main.invoke(null, new Object[]{new String[]{"main"}}));
}
public void testArrayWrite() throws Exception {
loadText("fun foo(c: Array<String>) { c[0] = \"jet\"; }");
final Method main = generateFunction();
String[] array = new String[] { null };
main.invoke(null, new Object[] { array });
assertEquals("jet", array[0]);
}
public void testArrayAugAssign() throws Exception {
loadText("fun foo(c: Array<Int>) { c[0] *= 2 }");
System.out.println(generateToText());
final Method main = generateFunction();
Integer[] data = new Integer[] { 5 };
main.invoke(null, new Object[] { data });
assertEquals(10, data[0].intValue());
}
public void testArrayAugAssignLong() throws Exception {
loadText("fun foo(c: LongArray) { c[0] *= 2 }");
System.out.println(generateToText());
final Method main = generateFunction();
long[] data = new long[] { 5 };
main.invoke(null, new Object[] { data });
assertEquals(10L, data[0]);
}
public void testArrayNew() throws Exception {
loadText("fun foo() = Array<Int>(4, { it })");
System.out.println(generateToText());
final Method main = generateFunction();
Integer[] result = (Integer[]) main.invoke(null);
assertEquals(4, result.length);
assertEquals(0, result[0].intValue());
assertEquals(1, result[1].intValue());
assertEquals(2, result[2].intValue());
assertEquals(3, result[3].intValue());
}
public void testArrayNewNullable() throws Exception {
loadText("fun foo() = Array<Int?>(4)");
System.out.println(generateToText());
final Method main = generateFunction();
Integer[] result = (Integer[]) main.invoke(null);
assertEquals(4, result.length);
}
public void testFloatArrayNew() throws Exception {
loadText("fun foo() = FloatArray(4)");
System.out.println(generateToText());
final Method main = generateFunction();
float[] result = (float[]) main.invoke(null);
assertEquals(4, result.length);
}
public void testFloatArrayArrayNew() throws Exception {
loadText("fun foo() = Array<FloatArray>(4, { FloatArray(5-it) })");
System.out.println(generateToText());
final Method main = generateFunction();
float[][] result = (float[][]) main.invoke(null);
assertEquals(4, result.length);
assertEquals(2, result[3].length);
}
public void testArraySize() throws Exception {
loadText("fun foo(a: Array<Int>) = a.size");
System.out.println(generateToText());
final Method main = generateFunction();
Object[] args = new Object[] { new Integer[4] };
int result = (Integer) main.invoke(null, args);
System.out.println(result);
assertEquals(4, result);
}
public void testIntArraySize() throws Exception {
loadText("fun foo(a: IntArray) = a.size");
System.out.println(generateToText());
final Method main = generateFunction();
Object[] args = new Object[] { new int[4] };
int result = (Integer) main.invoke(null, args);
assertEquals(4, result);
}
public void testIntRange() throws Exception {
loadText("fun foo() = 1..10");
final Method main = generateFunction();
IntRange result = (IntRange) main.invoke(null);
assertTrue(result.contains(1));
assertTrue(result.contains(10));
assertFalse(result.contains(11));
}
public void testSubstituteJavaMethodTypeParameters() throws Exception {
loadText("import java.util.*; fun foo(l: ArrayList<Int>) { l.add(10) }");
final Method main = generateFunction();
final ArrayList<Integer> l = new ArrayList<Integer>();
main.invoke(null, l);
assertEquals(10, l.get(0).intValue());
}
public void testCallMethodDeclaredInSuperclass() throws Exception {
loadText("fun foo(sb: StringBuilder) = sb.charAt(0)");
final Method main = generateFunction();
final StringBuilder sb = new StringBuilder("x");
assertEquals('x', ((Character) main.invoke(null, sb)).charValue());
}
public void testNamespaceQualifiedMethod() throws Exception {
blackBoxFile("namespaceQualifiedMethod.jet");
}
public void testCheckCast() throws Exception {
blackBoxFile("checkCast.jet");
}
public void testPutBooleanAsVoid() throws Exception {
loadText("class C(val x: Int) { { x > 0 } } fun box() { val c = C(0) } ");
final Method main = generateFunction();
main.invoke(null); // must not fail
}
public void testIncrementProperty() throws Exception {
blackBoxFile("incrementProperty.jet");
}
public void testJavaInterfaceMethod() throws Exception {
loadText("import java.util.*; fun foo(l: List<String>) { l.add(\"foo\") }");
final Method main = generateFunction();
final ArrayList<String> list = new ArrayList<String>();
main.invoke(null, list);
assertEquals("foo", list.get(0));
}
public void testArrayAccessForArrayList() throws Exception {
loadText("import java.util.*; fun foo(l: ArrayList<String>) { l[0] = \"Jet\" + l[0]; }");
final Method main = generateFunction();
final ArrayList<String> list = new ArrayList<String>();
list.add("Language");
main.invoke(null, list);
assertEquals("JetLanguage", list.get(0));
}
public void testTupleLiteral() throws Exception {
loadText("fun foo() = (1, \"foo\")");
System.out.println(generateToText());
final Method main = generateFunction();
Tuple2 tuple2 = (Tuple2) main.invoke(null);
assertEquals(1, tuple2._1);
assertEquals("foo", tuple2._2);
}
public void testParametrizedTupleLiteral() throws Exception {
loadText("fun <E,D> E.foo(extra: java.util.List<D>) = (1, \"foo\", this, extra)");
System.out.println(generateToText());
final Method main = generateFunction();
Tuple4 tuple4 = (Tuple4) main.invoke(null, "aaa", Arrays.asList(10), TypeInfo.STRING_TYPE_INFO, TypeInfo.INT_TYPE_INFO);
assertEquals(1, tuple4._1);
assertEquals("foo", tuple4._2);
assertEquals("aaa", tuple4._3);
}
public void testPredicateOperator() throws Exception {
loadText("fun foo(s: String) = s?startsWith(\"J\")");
final Method main = generateFunction();
try {
assertEquals("JetBrains", main.invoke(null, "JetBrains"));
assertNull(main.invoke(null, "IntelliJ"));
}
catch (Throwable t) {
System.out.println(generateToText());
t.printStackTrace();
}
}
public void testEscapeSequence() throws Exception {
loadText("fun foo() = \"a\\nb\\$\"");
final Method main = generateFunction();
assertEquals("a\nb$", main.invoke(null));
}
public void testStringTemplate() throws Exception {
loadText("fun foo(a: String) = \"IntelliJ $a Rulezzz\"");
final Method main = generateFunction();
assertEquals("IntelliJ IDEA Rulezzz", main.invoke(null, "IDEA"));
}
public void testExplicitCallOfBinaryOpIntrinsic() throws Exception {
loadText("fun foo(a: Int) = a.plus(1)");
final Method main = generateFunction();
assertEquals(2, ((Integer) main.invoke(null, 1)).intValue());
}
public void testExplicitCallOfUnaryMinusIntrinsic() throws Exception {
loadText("fun foo(a: Int) = a.minus()");
final Method main = generateFunction();
assertEquals(-1, ((Integer) main.invoke(null, 1)).intValue());
}
public void testExplicitCallOfBooleanNotIntrinsic() throws Exception {
loadText("fun foo(a: Boolean) = a.not()");
final Method main = generateFunction();
assertEquals(false, ((Boolean) main.invoke(null, true)).booleanValue());
}
public void testAppendArrayToString() throws Exception {
loadText("fun foo(a: String, b: Array<String>) = a + b");
final Method main = generateFunction();
final String[] args = new String[] { "foo", "bar" };
//noinspection ImplicitArrayToString
assertEquals("s" + args.toString(), main.invoke(null, "s", args));
}
}
@@ -0,0 +1,19 @@
package org.jetbrains.jet.codegen;
/**
* @author yole
*/
public class ObjectGenTest extends CodegenTestCase {
public void testSimpleObject() throws Exception {
blackBoxFile("objects/simpleObject.jet");
}
public void testObjectLiteral() throws Exception {
blackBoxFile("objects/objectLiteral.jet");
System.out.println(generateToText());
}
public void testMethodOnObject() throws Exception {
blackBoxFile("objects/methodOnObject.jet");
}
}
@@ -0,0 +1,133 @@
package org.jetbrains.jet.codegen;
import jet.NoPatternMatchedException;
import jet.Tuple2;
import java.lang.reflect.Method;
/**
* @author yole
*/
public class PatternMatchingTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "patternMatching";
}
public void testConstant() throws Exception {
loadFile();
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, 0));
assertFalse((Boolean) foo.invoke(null, 1));
}
public void testExceptionOnNoMatch() throws Exception {
loadFile();
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, 0));
assertThrows(foo, NoPatternMatchedException.class, null, 1);
}
public void testPattern() throws Exception {
loadFile();
Method foo = generateFunction();
assertEquals("string", foo.invoke(null, ""));
assertEquals("something", foo.invoke(null, new Object()));
}
public void testInrange() throws Exception {
loadFile();
System.out.println(generateToText());
Method foo = generateFunction();
assertEquals("array list", foo.invoke(null, 239));
assertEquals("digit", foo.invoke(null, 0));
assertEquals("digit", foo.invoke(null, 9));
assertEquals("digit", foo.invoke(null, 5));
assertEquals("not small", foo.invoke(null, 190));
assertEquals("something", foo.invoke(null, 19));
}
public void testIs() throws Exception {
loadFile();
System.out.println(generateToText());
blackBox();
}
public void testRange() throws Exception {
loadFile();
System.out.println(generateToText());
Method foo = generateFunction();
assertEquals("array list", foo.invoke(null, 239));
assertEquals("digit", foo.invoke(null, 0));
assertEquals("digit", foo.invoke(null, 9));
assertEquals("digit", foo.invoke(null, 5));
assertEquals("something", foo.invoke(null, 19));
assertEquals("not small", foo.invoke(null, 190));
}
public void testRangeChar() throws Exception {
loadFile();
System.out.println(generateToText());
Method foo = generateFunction();
assertEquals("digit", foo.invoke(null, '0'));
assertEquals("something", foo.invoke(null, 'A'));
}
public void testWildcardPattern() throws Exception {
loadText("fun foo(x: String) = when(x) { is * => \"something\" }");
Method foo = generateFunction();
assertEquals("something", foo.invoke(null, ""));
}
public void testNoReturnType() throws Exception {
loadText("fun foo(x: String) = when(x) { is * => \"x\" }");
Method foo = generateFunction();
assertEquals("x", foo.invoke(null, ""));
}
public void testTuplePattern() throws Exception {
loadText("fun foo(x: (Any, Any)) = when(x) { is (1,2) => \"one,two\"; else => \"something\" }");
Method foo = generateFunction();
final Object result;
try {
result = foo.invoke(null, new Tuple2<Integer, Integer>(null, 1, 2));
} catch (Exception e) {
System.out.println(generateToText());
throw e;
}
assertEquals("one,two", result);
assertEquals("something", foo.invoke(null, new Tuple2<String, String>(null, "not", "tuple")));
}
public void testCall() throws Exception {
loadText("fun foo(s: String) = when(s) { .startsWith(\"J\") => \"JetBrains\"; else => \"something\" }");
Method foo = generateFunction();
try {
assertEquals("JetBrains", foo.invoke(null, "Java"));
assertEquals("something", foo.invoke(null, "C#"));
}
catch (Throwable t) {
System.out.println(generateToText());
t.printStackTrace();
}
}
public void testCallProperty() throws Exception {
blackBoxFile("patternMatching/callProperty.jet");
}
public void testNames() throws Exception {
loadText("fun foo(x: (Any, Any)) = when(x) { is (val a is String, *) => a; else => \"something\" }");
Method foo = generateFunction();
assertEquals("JetBrains", foo.invoke(null, new Tuple2<String, String>(null, "JetBrains", "s.r.o.")));
assertEquals("something", foo.invoke(null, new Tuple2<Integer, Integer>(null, 1, 2)));
}
public void testMultipleConditions() throws Exception {
loadText("fun foo(x: Any) = when(x) { is 0, 1 => \"bit\"; else => \"something\" }");
Method foo = generateFunction();
assertEquals("bit", foo.invoke(null, 0));
assertEquals("bit", foo.invoke(null, 1));
assertEquals("something", foo.invoke(null, 2));
}
}
@@ -0,0 +1,277 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Method;
/**
* @author yole
*/
public class PrimitiveTypesTest extends CodegenTestCase {
public void testPlus() throws Exception {
loadText("fun f(a: Int, b: Int): Int { return a + b }");
System.out.println(generateToText());
final Method main = generateFunction();
final int returnValue = (Integer) main.invoke(null, 37, 5);
assertEquals(42, returnValue);
}
public void testGt() throws Exception {
loadText("fun foo(f: Int): Boolean { if (f > 0) return true; return false; }");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(true, main.invoke(null, 1));
assertEquals(false, main.invoke(null, 0));
}
public void testDiv() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a / b", 12, 3, 4);
}
public void testMod() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a % b", 14, 3, 2);
}
public void testNE() throws Exception {
loadText("fun foo(a: Int, b: Int): Int = if (a != b) 1 else 0");
final Method main = generateFunction();
assertEquals(0, main.invoke(null, 5, 5));
assertEquals(1, main.invoke(null, 5, 3));
}
public void testGE() throws Exception {
loadText("fun foo(a: Int, b: Int): Int = if (a >= b) 1 else 0");
final Method main = generateFunction();
assertEquals(1, main.invoke(null, 5, 5));
assertEquals(0, main.invoke(null, 3, 5));
}
public void testReturnCmp() throws Exception {
loadText("fun foo(a: Int, b: Int): Boolean = a == b");
final Method main = generateFunction();
assertEquals(true, main.invoke(null, 1, 1));
assertEquals(false, main.invoke(null, 1, 2));
}
public void testLong() throws Exception {
loadText("fun foo(a: Long, b: Long): Long = a + b");
System.out.println(generateToText());
final Method main = generateFunction();
long arg = (long) Integer.MAX_VALUE;
long expected = 2 * (long) Integer.MAX_VALUE;
assertEquals(expected, main.invoke(null, arg, arg));
}
public void testLongCmp() throws Exception {
loadText("fun foo(a: Long, b: Long): Long = if (a == b) 0xffffffff else 0xfffffffe");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(0xffffffffL, main.invoke(null, 1, 1));
assertEquals(0xfffffffeL, main.invoke(null, 1, 0));
}
public void testShort() throws Exception {
binOpTest("fun foo(a: Short, b: Short): Int = a + b",
Short.valueOf((short) 32767), Short.valueOf((short) 32767), 65534);
}
public void testShortCmp() throws Exception {
binOpTest("fun foo(a: Short, b: Short): Boolean = a == b",
Short.valueOf((short) 32767), Short.valueOf((short) 32767), true);
}
public void testByte() throws Exception {
binOpTest("fun foo(a: Byte, b: Byte): Int = a + b",
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 254);
}
public void testByteCmp() throws Exception {
binOpTest("fun foo(a: Byte, b: Byte): Int = if (a == b) 1 else 0",
Byte.valueOf((byte) 127), Byte.valueOf((byte) 127), 1);
}
public void testByteLess() throws Exception {
binOpTest("fun foo(a: Byte, b: Byte): Boolean = a < b",
Byte.valueOf((byte) 126), Byte.valueOf((byte) 127), true);
}
public void testBooleanConstant() throws Exception {
loadText("fun foo(): Boolean = true");
final Method main = generateFunction();
assertEquals(true, main.invoke(null));
}
public void testChar() throws Exception {
binOpTest("fun foo(a: Char, b: Char): Int = a + b", 'A', (char) 3, (int) 'D');
}
public void testFloat() throws Exception {
binOpTest("fun foo(a: Float, b: Float): Float = a + b", 1.0f, 2.0f, 3.0f);
}
public void testFloatCmp() throws Exception {
binOpTest("fun foo(a: Float, b: Float): Boolean = a == b", 1.0f, 1.0f, true);
}
public void testDouble() throws Exception {
binOpTest("fun foo(a: Double, b: Double): Double = a + b", 1.0, 2.0, 3.0);
}
public void testDoubleCmp() throws Exception {
binOpTest("fun foo(a: Double, b: Double): Boolean = a == b", 1.0, 2.0, false);
}
public void testDoubleToJava() throws Exception {
loadText("import java.lang.Double as jlDouble; fun foo(d: Double): String? = jlDouble.toString(d)");
final Method main = generateFunction();
assertEquals("1.0", main.invoke(null, 1.0));
}
public void testDoubleToInt() throws Exception {
loadText("fun foo(a: Double): Int = a.int");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(1, main.invoke(null, 1.0));
}
public void testCastConstant() throws Exception {
loadText("fun foo(): Double = 1.dbl");
final Method main = generateFunction();
assertEquals(1.0, main.invoke(null));
}
public void testCastOnStack() throws Exception {
loadText("fun foo(): Double = System.currentTimeMillis().dbl");
final Method main = generateFunction();
double currentTimeMillis = (double) System.currentTimeMillis();
double result = (Double) main.invoke(null);
double delta = Math.abs(currentTimeMillis - result);
assertTrue(delta <= 1.0);
}
public void testNeg() throws Exception {
loadText("fun foo(a: Int): Int = -a");
final Method main = generateFunction();
assertEquals(-10, main.invoke(null, 10));
}
public void testPreIncrement() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; ++x; return x;}");
final Method main = generateFunction();
assertEquals(11, main.invoke(null, 10));
}
public void testPreIncrementValue() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; return ++x;}");
final Method main = generateFunction();
assertEquals(11, main.invoke(null, 10));
}
public void testPreDecrement() throws Exception {
loadText("fun foo(a: Int): Int { return --a;}");
final Method main = generateFunction();
assertEquals(9, main.invoke(null, 10));
}
public void testPreIncrementLong() throws Exception {
loadText("fun foo(a: Long): Long = ++a");
final Method main = generateFunction();
assertEquals(11L, main.invoke(null, 10L));
}
public void testPreIncrementFloat() throws Exception {
loadText("fun foo(a: Float): Float = ++a");
final Method main = generateFunction();
assertEquals(2.0f, main.invoke(null, 1.0f));
}
public void testPreIncrementDouble() throws Exception {
loadText("fun foo(a: Double): Double = ++a");
final Method main = generateFunction();
assertEquals(2.0, main.invoke(null, 1.0));
}
public void testShl() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a shl b", 1, 3, 8);
}
public void testShr() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a shr b", 8, 3, 1);
}
public void testBitAnd() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a and b", 0x77, 0x1f, 0x17);
}
public void testBitOr() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a or b", 0x77, 0x1f, 0x7f);
}
public void testBitXor() throws Exception {
binOpTest("fun foo(a: Int, b: Int): Int = a xor b", 0x70, 0x1f, 0x6f);
}
public void testBitInv() throws Exception {
loadText("fun foo(a: Int): Int = a.inv()");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(0xffff0000, main.invoke(null, 0x0000ffff));
}
public void testMixedTypes() throws Exception {
binOpTest("fun foo(a: Int, b: Long): Long = a + b", 1, 2L, 3L);
}
public void testMixedTypes2() throws Exception {
binOpTest("fun foo(a: Double, b: Int): Double = a + b", 1.0, 2, 3.0);
}
public void testPostIncrementTypeInferenceFail() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; var y = x++; if (y+1 != x) return -1; return x; }");
final Method main = generateFunction();
assertEquals(6, main.invoke(null, 5));
}
public void testPostIncrement() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; var y = x++; return x*y; }");
final Method main = generateFunction();
assertEquals(6, main.invoke(null, 2));
}
public void testPostIncrementLong() throws Exception {
loadText("fun foo(a: Long): Long { var x = a; var y = x++; return x*y; }");
final Method main = generateFunction();
assertEquals(6L, main.invoke(null, 2L));
}
public void testDecrementAsStatement() throws Exception {
loadFile("bottles.jet");
System.out.println(generateToText());
final Method main = generateFunction();
main.invoke(null); // ensure no exception
}
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
loadText(text);
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(expected, main.invoke(null, arg1, arg2));
}
public void testKt242 () throws Exception {
blackBoxFile("regressions/kt242.jet");
}
public void testKt239 () throws Exception {
blackBoxFile("regressions/kt242.jet");
}
public void testKt243 () throws Exception {
blackBoxFile("regressions/kt243.jet");
}
public void testKt248 () throws Exception {
blackBoxFile("regressions/kt248.jet");
}
}
@@ -0,0 +1,143 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @author yole
*/
public class PropertyGenTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "properties";
}
public void testPrivateVal() throws Exception {
loadFile();
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVal");
final Field[] fields = aClass.getDeclaredFields();
assertEquals(2, fields.length); // $typeInfo, prop
final Field field = fields[0];
assertEquals("prop", field.getName());
}
public void testPrivateVar() throws Exception {
loadFile();
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVar");
final Object instance = aClass.newInstance();
Method setter = findMethodByName(aClass, "setValueOfX");
setter.invoke(instance, 239);
Method getter = findMethodByName(aClass, "getValueOfX");
assertEquals(239, ((Integer) getter.invoke(instance)).intValue());
}
public void testPublicVar() throws Exception {
loadText("class PublicVar() { public var foo : Int = 0; }");
final Class aClass = loadImplementationClass(generateClassesInFile(), "PublicVar");
final Object instance = aClass.newInstance();
Method setter = findMethodByName(aClass, "setFoo");
setter.invoke(instance, 239);
Method getter = findMethodByName(aClass, "getFoo");
assertEquals(239, ((Integer) getter.invoke(instance)).intValue());
}
public void testAccessorsInInterface() {
loadText("class AccessorsInInterface() { public var foo : Int = 0; }");
final Class aClass = loadClass("AccessorsInInterface", generateClassesInFile());
assertNotNull(findMethodByName(aClass, "getFoo"));
assertNotNull(findMethodByName(aClass, "setFoo"));
}
public void testPropertyInNamespace() throws Exception {
loadText("private val x = 239");
final Class nsClass = generateNamespaceClass();
final Field[] fields = nsClass.getDeclaredFields();
assertEquals(1, fields.length);
final Field field = fields[0];
field.setAccessible(true);
assertEquals("x", field.getName());
assertEquals(Modifier.PRIVATE | Modifier.STATIC, field.getModifiers());
assertEquals(239, field.get(null));
}
public void testFieldPropertyAccess() throws Exception {
loadFile("properties/fieldPropertyAccess.jet");
final Method method = generateFunction();
assertEquals(1, method.invoke(null));
assertEquals(2, method.invoke(null));
}
public void testFieldGetter() throws Exception {
loadText("val now: Long get() = System.currentTimeMillis(); fun foo() = now");
final Method method = generateFunction("foo");
assertIsCurrentTime((Long) method.invoke(null));
}
public void testFieldSetter() throws Exception {
loadFile();
final Method method = generateFunction("append");
method.invoke(null, "IntelliJ ");
String value = (String) method.invoke(null, "IDEA");
if (!value.equals("IntelliJ IDEA")) {
System.out.println(generateToText());
}
assertEquals("IntelliJ IDEA", value);
}
public void testFieldSetterPlusEq() throws Exception {
loadFile();
final Method method = generateFunction("append");
method.invoke(null, "IntelliJ ");
String value = (String) method.invoke(null, "IDEA");
assertEquals("IntelliJ IDEA", value);
}
public void testAccessorsWithoutBody() throws Exception {
loadText("class AccessorsWithoutBody() { public var foo: Int = 349\n get\n private set\n fun setter() { foo = 610; } } ");
final Class aClass = loadImplementationClass(generateClassesInFile(), "AccessorsWithoutBody");
final Object instance = aClass.newInstance();
final Method getFoo = findMethodByName(aClass, "getFoo");
assertEquals(349, getFoo.invoke(instance));
final Method setFoo = findMethodByName(aClass, "setFoo");
assertTrue((setFoo.getModifiers() & Modifier.PRIVATE) != 0);
final Method setter = findMethodByName(aClass, "setter");
setter.invoke(instance);
assertEquals(610, getFoo.invoke(instance));
}
public void testInitializersForNamespaceProperties() throws Exception {
loadText("val x = System.currentTimeMillis()");
final Method method = generateFunction("getX");
assertIsCurrentTime((Long) method.invoke(null));
}
public void testPropertyReceiverOnStack() throws Exception {
loadFile();
final Class aClass = loadImplementationClass(generateClassesInFile(), "Evaluator");
final Constructor constructor = aClass.getConstructor(StringBuilder.class);
StringBuilder sb = new StringBuilder("xyzzy");
final Object instance = constructor.newInstance(sb);
final Method method = aClass.getMethod("evaluateArg");
Integer result = (Integer) method.invoke(instance);
assertEquals(5, result.intValue());
}
public void testAbstractVal() throws Exception {
loadText("abstract class Foo { public abstract val x: String }");
final ClassFileFactory codegens = generateClassesInFile();
final Class aClass = loadClass("Foo", codegens);
assertNotNull(aClass.getMethod("getX"));
}
public void testKt257 () throws Exception {
blackBoxFile("regressions/kt257.jet");
}
public void testKt160() throws Exception {
loadText("internal val s = java.lang.Double.toString(1.0)");
final Method method = generateFunction("getS");
assertEquals(method.invoke(null), "1.0");
}
}
@@ -0,0 +1,15 @@
package org.jetbrains.jet.codegen;
public class SafeRefTest extends CodegenTestCase {
public void test247 () throws Exception {
blackBoxFile("regressions/kt247.jet");
}
public void test245 () throws Exception {
blackBoxFile("regressions/kt245.jet");
}
public void test232 () throws Exception {
blackBoxFile("regressions/kt232.jet");
}
}
@@ -0,0 +1,26 @@
package org.jetbrains.jet.codegen;
public class TraitsTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "traits";
}
public void testSimple () throws Exception {
blackBoxFile("traits/simple.jet");
System.out.println(generateToText());
}
public void testWithRequired () throws Exception {
blackBoxFile("traits/withRequired.jet");
System.out.println(generateToText());
}
public void testMultiple () throws Exception {
blackBoxFile("traits/multiple.jet");
}
public void testStdlib () throws Exception {
blackBoxFile("traits/stdlib.jet");
}
}
@@ -0,0 +1,143 @@
package org.jetbrains.jet.codegen;
import jet.JetObject;
import jet.TypeCastException;
import jet.typeinfo.TypeInfo;
import java.lang.reflect.Method;
/**
* @author yole
*/
public class TypeInfoTest extends CodegenTestCase {
@Override
protected String getPrefix() {
return "typeInfo";
}
public void testGetTypeInfo() throws Exception {
loadFile();
Method foo = generateFunction();
JetObject jetObject = (JetObject) foo.invoke(null);
TypeInfo<?> typeInfo = jetObject.getTypeInfo();
assertNotNull(typeInfo);
}
public void testOneArgTypeinfo() throws Exception {
loadFile();
Method foo = generateFunction();
TypeInfo typeInfo = (TypeInfo) foo.invoke(null);
assertNotNull(typeInfo);
}
public void testNoArgTypeinfo() throws Exception {
loadText("fun foo() = typeinfo.typeinfo<Int>()");
Method foo = generateFunction();
TypeInfo typeInfo = (TypeInfo) foo.invoke(null);
assertSame(TypeInfo.INT_TYPE_INFO, typeInfo);
}
public void testAsSafeOperator() throws Exception {
loadText("fun foo(x: Any) = x as? Runnable");
Method foo = generateFunction();
assertNull(foo.invoke(null, new Object()));
Runnable r = newRunnable();
assertSame(r, foo.invoke(null, r));
}
public void testAsOperator() throws Exception {
loadText("fun foo(x: Any) = x as Runnable");
Method foo = generateFunction();
Runnable r = newRunnable();
assertSame(r, foo.invoke(null, r));
assertThrows(foo, TypeCastException.class, null, new Object());
}
public void testIsOperator() throws Exception {
loadText("fun foo(x: Any) = x is Runnable");
Method foo = generateFunction();
assertFalse((Boolean) foo.invoke(null, new Object()));
assertTrue((Boolean) foo.invoke(null, newRunnable()));
}
public void testIsWithGenerics() throws Exception {
loadFile();
System.out.println(generateToText());
Method foo = generateFunction();
assertFalse((Boolean) foo.invoke(null));
}
public void testNotIsOperator() throws Exception {
loadText("fun foo(x: Any) = x !is Runnable");
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, new Object()));
assertFalse((Boolean) foo.invoke(null, newRunnable()));
}
public void testIsWithGenericParameters() throws Exception {
loadFile();
Method foo = generateFunction();
assertFalse((Boolean) foo.invoke(null));
}
public void testIsTypeParameter() throws Exception {
blackBoxFile("typeInfo/isTypeParameter.jet");
}
public void testAsSafeWithGenerics() throws Exception {
loadFile();
Method foo = generateFunction();
assertNull(foo.invoke(null));
}
public void testAsInLoop() throws Exception {
loadFile();
generateFunction(); // assert no exception
}
public void testPrimitiveTypeInfo() throws Exception {
blackBoxFile("typeInfo/primitiveTypeInfo.jet");
}
public void testNullability() throws Exception {
blackBoxFile("typeInfo/nullability.jet");
}
public void testGenericFunction() throws Exception {
blackBoxFile("typeInfo/genericFunction.jet");
}
public void testForwardTypeParameter() throws Exception {
blackBoxFile("typeInfo/forwardTypeParameter.jet");
}
public void testClassObjectInTypeInfo() throws Exception {
loadFile();
System.out.println(generateToText());
Method foo = generateFunction();
JetObject jetObject = (JetObject) foo.invoke(null);
TypeInfo<?> typeInfo = jetObject.getTypeInfo();
final Object object = typeInfo.getClassObject();
final Method classObjFoo = object.getClass().getMethod("foo");
assertNotNull(classObjFoo);
}
private Runnable newRunnable() {
return new Runnable() {
@Override
public void run() {
}
};
}
public void testKt259() throws Exception {
blackBoxFile("regressions/kt259.jet");
System.out.println(generateToText());
}
public void testInner() throws Exception {
blackBoxFile("typeInfo/inner.jet");
System.out.println(generateToText());
}
}
@@ -0,0 +1,61 @@
package org.jetbrains.jet.parsing;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author abreslav
*/
public class JetCodeConformanceTest extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite();
TestSuite ats = new TestSuite("Side-effect-free at()'s in assertions");
suite.addTest(ats);
File parsingSourceDir = new File("./compiler/frontend/src/org/jetbrains/jet/lang/parsing");
for (File sourceFile : parsingSourceDir.listFiles()) {
if (sourceFile.getName().endsWith(".java")) {
ats.addTest(new JetCodeConformanceTest(sourceFile.getName(), sourceFile));
}
}
return suite;
}
private final File sourceFile;
public JetCodeConformanceTest(String name, File sourceFile) {
super(name);
this.sourceFile = sourceFile;
}
@Override
protected void runTest() throws Throwable {
checkSourceFile(sourceFile);
}
private void checkSourceFile(File sourceFile) throws IOException {
FileReader reader = new FileReader(sourceFile);
StringBuilder builder = new StringBuilder();
int c;
while ((c = reader.read()) >= 0) {
builder.append((char) c);
}
String source = builder.toString();
Pattern atPattern = Pattern.compile("assert.*?[^_]at.*?$", Pattern.MULTILINE);
Matcher matcher = atPattern.matcher(source);
boolean match = matcher.find();
if (match) {
fail("An at-method with side-ffects is used inside assert: " + matcher.group());
}
}
}
@@ -0,0 +1,117 @@
/*
* @author max
*/
package org.jetbrains.jet.parsing;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.ParsingTestCase;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetVisitorVoid;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class JetParsingTest extends ParsingTestCase {
static {
System.setProperty("idea.platform.prefix", "Idea");
}
private final String name;
public JetParsingTest(String dataPath, String name) {
super(dataPath, "jet", new JetParserDefinition());
this.name = name;
}
@Override
protected String getTestDataPath() {
return getTestDataDir() + "/psi";
}
public static String getTestDataDir() {
return getHomeDirectory() + "/compiler/testData";
}
private static String getHomeDirectory() {
File root = new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class"));
return FileUtil.toSystemIndependentName(root.getParentFile().getParentFile().getParent());
}
@Override
protected void checkResult(@NonNls String targetDataName, PsiFile file) throws IOException {
file.acceptChildren(new JetVisitorVoid() {
@Override
public void visitJetElement(JetElement element) {
element.acceptChildren(this);
try {
checkPsiGetters(element);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
});
super.checkResult(targetDataName, file);
}
private void checkPsiGetters(JetElement elem) throws Throwable {
Method[] methods = elem.getClass().getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();
if (!methodName.startsWith("get") && !methodName.startsWith("find") || methodName.equals("getReference") || methodName.equals("getReferences")) continue;
if (method.getParameterTypes().length > 0) continue;
Class<?> declaringClass = method.getDeclaringClass();
if (!declaringClass.getName().startsWith("org.jetbrains.jet")) continue;
Object result = method.invoke(elem);
if (result == null) {
for (Annotation annotation : method.getDeclaredAnnotations()) {
if (annotation instanceof JetElement.IfNotParsed) {
assertNotNull(
"Incomplete operation in parsed OK test, method " + methodName +
" in " + declaringClass.getSimpleName() + " returns null. Element text: \n" + elem.getText(),
PsiTreeUtil.findChildOfType(elem, PsiErrorElement.class));
}
}
}
}
}
@Override
protected void runTest() throws Throwable {
doTest(true);
}
@Override
public String getName() {
return "test" + name;
}
public static TestSuite suite() {
TestSuite suite = new TestSuite();
JetTestCaseBase.NamedTestFactory factory = new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetParsingTest(dataPath, name);
}
};
String prefix = JetParsingTest.getTestDataDir() + "/psi/";
suite.addTest(JetTestCaseBase.suiteForDirectory(prefix, "/", false, factory));
suite.addTest(JetTestCaseBase.suiteForDirectory(prefix, "examples", true, factory));
return suite;
}
}
@@ -0,0 +1,295 @@
package org.jetbrains.jet.resolve;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static junit.framework.Assert.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
/**
* @author abreslav
*/
public class ExpectedResolveData {
private final Map<String, Integer> declarationToPosition = new HashMap<String, Integer>();
private final Map<Integer, String> positionToReference = new HashMap<Integer, String>();
private final Map<Integer, String> positionToType = new HashMap<Integer, String>();
private final Map<String, DeclarationDescriptor> nameToDescriptor;
private final Map<String, PsiElement> nameToPsiElement;
// private final Map<String, JetType> nameToType;
public ExpectedResolveData(Map<String, DeclarationDescriptor> nameToDescriptor, Map<String, PsiElement> nameToPsiElement/*, Map<String, JetType> nameToType*/) {
this.nameToDescriptor = nameToDescriptor;
this.nameToPsiElement = nameToPsiElement;
// this.nameToType = nameToType;
}
public void extractData(final Document document) {
new WriteCommandAction.Simple(null) {
public void run() {
doExtractData(document);
}
}.execute().throwException();
}
private void doExtractData(Document document) {
String text = document.getText();
Pattern pattern = Pattern.compile("(~[^~]+~)|(`[^`]+`)");
while (true) {
Matcher matcher = pattern.matcher(text);
if (!matcher.find()) break;
String group = matcher.group();
String name = group.substring(1, group.length() - 1);
int start = matcher.start();
if (group.startsWith("~")) {
if (declarationToPosition.put(name, start) != null) {
throw new IllegalArgumentException("Redeclaration: " + name);
}
}
else if (group.startsWith("`")) {
if (name.startsWith(":")) {
positionToType.put(start - 1, name.substring(1));
}
else {
positionToReference.put(start, name);
}
}
else {
throw new IllegalStateException();
}
document.replaceString(start, matcher.end(), "");
text = document.getText();
}
System.out.println(text);
}
public void checkResult(JetFile file) {
final Set<PsiElement> unresolvedReferences = new HashSet<PsiElement>();
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(file.getProject());
JetStandardLibrary lib = semanticServices.getStandardLibrary();
BindingContext bindingContext = AnalyzerFacade.analyzeNamespace(file.getRootNamespace(), JetControlFlowDataTraceFactory.EMPTY);
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic) diagnostic;
unresolvedReferences.add(unresolvedReferenceDiagnostic.getPsiElement());
}
}
Map<String, JetDeclaration> nameToDeclaration = new HashMap<String, JetDeclaration>();
Map<JetDeclaration, String> declarationToName = new HashMap<JetDeclaration, String>();
for (Map.Entry<String, Integer> entry : declarationToPosition.entrySet()) {
String name = entry.getKey();
Integer position = entry.getValue();
PsiElement element = file.findElementAt(position);
JetDeclaration ancestorOfType = getAncestorOfType(JetDeclaration.class, element);
nameToDeclaration.put(name, ancestorOfType);
declarationToName.put(ancestorOfType, name);
}
for (Map.Entry<Integer, String> entry : positionToReference.entrySet()) {
Integer position = entry.getKey();
String name = entry.getValue();
PsiElement element = file.findElementAt(position);
JetReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(element, JetReferenceExpression.class);
if ("!".equals(name)) {
assertTrue(
"Must have been unresolved: " +
renderReferenceInContext(referenceExpression) +
" but was resolved to " + DescriptorRenderer.TEXT.render(bindingContext.get(REFERENCE_TARGET, referenceExpression)),
unresolvedReferences.contains(referenceExpression));
continue;
}
if ("!!".equals(name)) {
assertTrue(
"Must have been resolved to multiple descriptors: " +
renderReferenceInContext(referenceExpression) +
" but was resolved to " + DescriptorRenderer.TEXT.render(bindingContext.get(REFERENCE_TARGET, referenceExpression)),
bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, referenceExpression) != null);
continue;
}
else if ("!null".equals(name)) {
assertTrue(
"Must have been resolved to null: " +
renderReferenceInContext(referenceExpression) +
" but was resolved to " + DescriptorRenderer.TEXT.render(bindingContext.get(REFERENCE_TARGET, referenceExpression)),
bindingContext.get(REFERENCE_TARGET, referenceExpression) == null
);
continue;
}
else if ("!error".equals(name)) {
assertTrue(
"Must have been resolved to error: " +
renderReferenceInContext(referenceExpression) +
" but was resolved to " + DescriptorRenderer.TEXT.render(bindingContext.get(REFERENCE_TARGET, referenceExpression)),
ErrorUtils.isError(bindingContext.get(REFERENCE_TARGET, referenceExpression))
);
continue;
}
PsiElement expected = nameToDeclaration.get(name);
if (expected == null && name.startsWith("$")) {
expected = nameToDeclaration.get(name.substring(1));
}
if (expected == null) {
expected = nameToPsiElement.get(name);
}
JetReferenceExpression reference = getAncestorOfType(JetReferenceExpression.class, element);
if (expected == null && name.startsWith("std::")) {
DeclarationDescriptor expectedDescriptor = nameToDescriptor.get(name);
JetTypeReference typeReference = getAncestorOfType(JetTypeReference.class, element);
if (expectedDescriptor != null) {
DeclarationDescriptor actual = bindingContext.get(REFERENCE_TARGET, reference);
assertSame("Expected: " + name, expectedDescriptor.getOriginal(), actual == null
? null
: actual.getOriginal());
continue;
}
JetType actualType = bindingContext.get(BindingContext.TYPE, typeReference);
assertNotNull("Type " + name + " not resolved for reference " + name, actualType);
ClassifierDescriptor expectedClass = lib.getLibraryScope().getClassifier(name.substring(5));
assertNotNull("Expected class not found: " + name);
assertSame("Type resolution mismatch: ", expectedClass.getTypeConstructor(), actualType.getConstructor());
continue;
}
assert expected != null : "No declaration for " + name;
PsiElement actual = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, reference);
String actualName = null;
if (actual != null) {
actualName = declarationToName.get(actual);
if (actualName == null) {
actualName = actual.toString();
}
}
assertNotNull(element.getText(), reference);
if (expected instanceof JetParameter || actual instanceof JetParameter) {
DeclarationDescriptor expectedDescriptor;
if (name.startsWith("$")) {
expectedDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, (JetParameter) expected);
}
else {
expectedDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expected);
if (expectedDescriptor == null) {
expectedDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, (JetElement) expected);
}
}
DeclarationDescriptor actualDescriptor = bindingContext.get(REFERENCE_TARGET, reference);
if (actualDescriptor instanceof VariableAsFunctionDescriptor) {
VariableAsFunctionDescriptor descriptor = (VariableAsFunctionDescriptor) actualDescriptor;
actualDescriptor = descriptor.getVariableDescriptor();
}
assertEquals(
"Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".",
expectedDescriptor, actualDescriptor);
}
else {
assertEquals(
"Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".",
expected, actual);
}
}
for (Map.Entry<Integer, String> entry : positionToType.entrySet()) {
Integer position = entry.getKey();
String typeName = entry.getValue();
PsiElement element = file.findElementAt(position);
JetExpression expression = getAncestorOfType(JetExpression.class, element);
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
TypeConstructor expectedTypeConstructor;
if (typeName.startsWith("std::")) {
ClassifierDescriptor expectedClass = lib.getLibraryScope().getClassifier(typeName.substring(5));
assertNotNull("Expected class not found: " + typeName, expectedClass);
expectedTypeConstructor = expectedClass.getTypeConstructor();
} else {
Integer declarationPosition = declarationToPosition.get(typeName);
assertNotNull("Undeclared: " + typeName, declarationPosition);
PsiElement declElement = file.findElementAt(declarationPosition);
assertNotNull(declarationPosition);
JetDeclaration declaration = getAncestorOfType(JetDeclaration.class, declElement);
assertNotNull(declaration);
if (declaration instanceof JetClass) {
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, (JetClass) declaration);
expectedTypeConstructor = classDescriptor.getTypeConstructor();
}
else if (declaration instanceof JetTypeParameter) {
TypeParameterDescriptor typeParameterDescriptor = bindingContext.get(BindingContext.TYPE_PARAMETER, (JetTypeParameter) declaration);
expectedTypeConstructor = typeParameterDescriptor.getTypeConstructor();
}
else {
fail("Unsupported declaration: " + declaration);
return;
}
}
assertNotNull(expression.getText() + " type is null", expressionType);
assertSame("At " + position + ": ", expectedTypeConstructor, expressionType.getConstructor());
}
}
private static String renderReferenceInContext(JetReferenceExpression referenceExpression) {
JetExpression statement = referenceExpression;
while (true) {
PsiElement parent = statement.getParent();
if (!(parent instanceof JetExpression)) break;
if (parent instanceof JetBlockExpression) break;
statement = (JetExpression) parent;
}
JetDeclaration declaration = PsiTreeUtil.getParentOfType(referenceExpression, JetDeclaration.class);
return referenceExpression.getText() + " at " + DiagnosticUtils.atLocation(referenceExpression) +
" in " + statement.getText() + (declaration == null ? "" : " in " + declaration.getText());
}
private static <T> T getAncestorOfType(Class<T> type, PsiElement element) {
while (element != null && !type.isInstance(element)) {
element = element.getParent();
}
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
T result = (T) element;
return result;
}
}
@@ -0,0 +1,108 @@
package org.jetbrains.jet.resolve;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.testFramework.FileTreeAccessFilter;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
import java.util.Collection;
import java.util.List;
/**
* @author abreslav
*/
public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase {
private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
private ExpectedResolveData expectedResolveData;
@Override
protected void setUp() throws Exception {
super.setUp();
expectedResolveData = getExpectedResolveData();
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).prepareForTest();
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
}
protected abstract ExpectedResolveData getExpectedResolveData();
@Override
protected void tearDown() throws Exception {
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(false); // has to cleanup by hand since light project does not get disposed any time soon
super.tearDown();
}
@Override
protected void runTest() throws Throwable {
final Throwable[] throwable = {null};
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
try {
doRunTest();
} catch (Throwable t) {
throwable[0] = t;
}
}
}, "", null);
if (throwable[0] != null) {
throw throwable[0];
}
}
protected void doTest(@NonNls String filePath, boolean checkWarnings, boolean checkInfos) throws Exception {
configureByFile(filePath);
doTestConfiguredFile(checkWarnings, checkInfos);
}
protected void doTestConfiguredFile(boolean checkWarnings, boolean checkInfos) {
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
// ExpectedHighlightingData expectedData = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos);
expectedResolveData.extractData(getEditor().getDocument());
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
getFile().getText(); //to load text
myJavaFilesFilter.allowTreeAccessForFile(getVFile());
getJavaFacade().setAssertOnFileLoadingFilter(myJavaFilesFilter); // check repository work
Collection<HighlightInfo> infos = doHighlighting();
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
expectedResolveData.checkResult((JetFile) getFile());
}
@NotNull
protected List<HighlightInfo> doHighlighting() {
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
int[] toIgnore = doFolding() ? ArrayUtil.EMPTY_INT_ARRAY : new int[]{Pass.UPDATE_FOLDING};
Editor editor = getEditor();
PsiFile file = getFile();
if (editor instanceof EditorWindow) {
editor = ((EditorWindow) editor).getDelegate();
file = InjectedLanguageUtil.getTopLevelFile(file);
}
return CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, toIgnore, false);
}
protected boolean doFolding() {
return false;
}
}
@@ -0,0 +1,164 @@
package org.jetbrains.jet.resolve;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import junit.framework.Test;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.File;
import java.util.*;
/**
* @author abreslav
*/
public class JetResolveTest extends ExtensibleResolveTestCase {
private final String path;
private final String name;
public JetResolveTest(String path, String name) {
this.path = path;
this.name = name;
}
@Override
protected ExpectedResolveData getExpectedResolveData() {
Project project = getProject();
JetStandardLibrary lib = JetStandardLibrary.getJetStandardLibrary(project);
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
FunctionDescriptor descriptorForGet = standardFunction(lib.getArray(), Collections.singletonList(new TypeProjection(lib.getIntType())), "get", lib.getIntType());
nameToDescriptor.put("std::Array.get(Int)", descriptorForGet.getOriginal());
nameToDescriptor.put("std::Int.compareTo(Double)", standardFunction(lib.getInt(), "compareTo", lib.getDoubleType()));
@NotNull
FunctionDescriptor descriptorForSet = standardFunction(lib.getArray(), Collections.singletonList(new TypeProjection(lib.getIntType())), "set", lib.getIntType(), lib.getIntType());
nameToDescriptor.put("std::Array.set(Int, Int)", descriptorForSet.getOriginal());
Map<String,PsiElement> nameToDeclaration = new HashMap<String, PsiElement>();
PsiClass java_util_Collections = findClass("java.util.Collections");
nameToDeclaration.put("java::java.util.Collections.emptyList()", findMethod(java_util_Collections, "emptyList"));
nameToDeclaration.put("java::java.util.Collections", java_util_Collections);
PsiClass java_util_List = findClass("java.util.List");
nameToDeclaration.put("java::java.util.List", java_util_List);
nameToDeclaration.put("java::java.util.List.set()", java_util_List.findMethodsByName("set", true)[0]);
nameToDeclaration.put("java::java.util.List.get()", java_util_List.findMethodsByName("get", true)[0]);
nameToDeclaration.put("java::java", findPackage("java"));
nameToDeclaration.put("java::java.util", findPackage("java.util"));
nameToDeclaration.put("java::java.lang", findPackage("java.lang"));
nameToDeclaration.put("java::java.lang.Object", findClass("java.lang.Object"));
PsiClass java_lang_System = findClass("java.lang.System");
nameToDeclaration.put("java::java.lang.System", java_lang_System);
PsiMethod[] methods = findClass("java.io.PrintStream").findMethodsByName("print", true);
nameToDeclaration.put("java::java.io.PrintStream.print(Object)", methods[8]);
nameToDeclaration.put("java::java.io.PrintStream.print(Int)", methods[2]);
nameToDeclaration.put("java::java.io.PrintStream.print(char[])", methods[6]);
nameToDeclaration.put("java::java.io.PrintStream.print(Double)", methods[5]);
nameToDeclaration.put("java::java.lang.System.out", java_lang_System.findFieldByName("out", true));
PsiClass java_lang_Number = findClass("java.lang.Number");
nameToDeclaration.put("java::java.lang.Number", java_lang_Number);
nameToDeclaration.put("java::java.lang.Number.intValue()", java_lang_Number.findMethodsByName("intValue", true)[0]);
return new ExpectedResolveData(nameToDescriptor, nameToDeclaration);
}
@NotNull
private PsiElement findPackage(String qualifiedName) {
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(getProject());
return javaFacade.findPackage(qualifiedName);
}
@NotNull
private PsiMethod findMethod(PsiClass psiClass, String name) {
PsiMethod[] emptyLists = psiClass.findMethodsByName(name, true);
return emptyLists[0];
}
@NotNull
private PsiClass findClass(String qualifiedName) {
Project project = getProject();
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(project);
GlobalSearchScope javaSearchScope = GlobalSearchScope.allScope(project);
return javaFacade.findClass(qualifiedName, javaSearchScope);
}
@NotNull
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, String name, JetType parameterType) {
List<TypeProjection> typeArguments = Collections.emptyList();
return standardFunction(classDescriptor, typeArguments, name, parameterType);
}
@NotNull
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List<TypeProjection> typeArguments, String name, JetType... parameterType) {
List<JetType> parameterTypeList = Arrays.asList(parameterType);
// JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext());
CallResolver callResolver = new CallResolver(JetSemanticServices.createSemanticServices(getProject()), DataFlowInfo.EMPTY);
OverloadResolutionResults<FunctionDescriptor> functions = callResolver.resolveExactSignature(
classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList);
for (ResolvedCallImpl<FunctionDescriptor> resolvedCall : functions.getResults()) {
List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
if (unsubstitutedValueParameter.getOutType().equals(parameterType[i])) {
return resolvedCall.getResultingDescriptor();
}
}
}
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterTypeList + ")");
}
@Override
protected String getTestDataPath() {
return getHomeDirectory() + "/compiler/testData";
}
@Override
protected Sdk getProjectJDK() {
return JetTestCaseBase.jdkFromIdeaHome();
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
}
@Override
public String getName() {
return "test" + name;
}
@Override
protected void runTest() throws Throwable {
doTest(path, true, false);
}
public static Test suite() {
return JetTestCaseBase.suiteForDirectory(getHomeDirectory() + "/compiler/testData/", "/resolve/", true, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetResolveTest(dataPath + "/" + name + ".jet", name);
}
});
}
}
@@ -0,0 +1,400 @@
package org.jetbrains.jet.types;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import java.util.List;
/**
* @author svtk
*/
public class JetDefaultModalityModifiersTest extends LightDaemonAnalyzerTestCase {
private JetDefaultModalityModifiersTestCase tc = new JetDefaultModalityModifiersTestCase();
@Override
public void setUp() throws Exception {
super.setUp();
tc.setUp();
}
public static class JetDefaultModalityModifiersTestCase {
private ModuleDescriptor root = new ModuleDescriptor("test_root");
private ClassDescriptorResolver classDescriptorResolver;
private JetScope scope;
public void setUp() throws Exception {
JetStandardLibrary library = JetStandardLibrary.getJetStandardLibrary(getProject());
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(library);
classDescriptorResolver = semanticServices.getClassDescriptorResolver(JetTestUtils.DUMMY_EXCEPTION_ON_ERROR_TRACE);
scope = createScope(library.getLibraryScope());
}
private JetScope createScope(JetScope libraryScope) {
JetFile file = JetPsiFactory.createFile(getProject(), "abstract class C { abstract fun foo(); abstract val a: Int }");
List<JetDeclaration> declarations = file.getRootNamespace().getDeclarations();
JetDeclaration aClass = declarations.get(0);
assert aClass instanceof JetClass;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
DeclarationDescriptor classDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING);
assert classDescriptor instanceof ClassifierDescriptor;
scope.addClassifierDescriptor((ClassifierDescriptor) classDescriptor);
return scope;
}
private MutableClassDescriptor createClassDescriptor(ClassKind kind, JetClass aClass) {
MutableClassDescriptor classDescriptor = new MutableClassDescriptor(JetTestUtils.DUMMY_TRACE, root, scope, kind);
classDescriptorResolver.resolveMutableClassDescriptor(aClass, classDescriptor);
return classDescriptor;
}
private void testClassModality(String classDeclaration, ClassKind kind, Modality expectedModality) {
JetClass aClass = JetPsiFactory.createClass(getProject(), classDeclaration);
MutableClassDescriptor classDescriptor = createClassDescriptor(kind, aClass);
assertEquals(expectedModality, classDescriptor.getModality());
}
private void testFunctionModality(String classWithFunction, ClassKind kind, Modality expectedFunctionModality) {
JetClass aClass = JetPsiFactory.createClass(getProject(), classWithFunction);
MutableClassDescriptor classDescriptor = createClassDescriptor(kind, aClass);
List<JetDeclaration> declarations = aClass.getDeclarations();
JetNamedFunction function = (JetNamedFunction) declarations.get(0);
FunctionDescriptorImpl functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(classDescriptor, scope, function);
assertEquals(expectedFunctionModality, functionDescriptor.getModality());
}
private void testPropertyModality(String classWithProperty, ClassKind kind, Modality expectedPropertyModality) {
JetClass aClass = JetPsiFactory.createClass(getProject(), classWithProperty);
MutableClassDescriptor classDescriptor = createClassDescriptor(kind, aClass);
List<JetDeclaration> declarations = aClass.getDeclarations();
JetProperty property = (JetProperty) declarations.get(0);
PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(classDescriptor, scope, property);
assertEquals(expectedPropertyModality, propertyDescriptor.getModality());
}
private void testPropertyAccessorModality(String classWithPropertyWithAccessor, ClassKind kind, Modality expectedPropertyAccessorModality, boolean isGetter) {
JetClass aClass = JetPsiFactory.createClass(getProject(), classWithPropertyWithAccessor);
MutableClassDescriptor classDescriptor = createClassDescriptor(kind, aClass);
List<JetDeclaration> declarations = aClass.getDeclarations();
JetProperty property = (JetProperty) declarations.get(0);
PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(classDescriptor, scope, property);
PropertyAccessorDescriptor propertyAccessor = isGetter
? propertyDescriptor.getGetter()
: propertyDescriptor.getSetter();
assert propertyAccessor != null;
assertEquals(expectedPropertyAccessorModality, propertyAccessor.getModality());
}
public void testClassModality(String classDeclaration, Modality expectedModality) {
testClassModality(classDeclaration, ClassKind.CLASS, expectedModality);
}
public void testTraitModality(String classDeclaration, Modality expectedModality) {
testClassModality(classDeclaration, ClassKind.TRAIT, expectedModality);
}
public void testEnumModality(String classDeclaration, Modality expectedModality) {
testClassModality(classDeclaration, ClassKind.ENUM_CLASS, expectedModality);
}
public void testFunctionModalityInClass(String classWithFunction, Modality expectedModality) {
testFunctionModality(classWithFunction, ClassKind.CLASS, expectedModality);
}
public void testFunctionModalityInEnum(String classWithFunction, Modality expectedModality) {
testFunctionModality(classWithFunction, ClassKind.ENUM_CLASS, expectedModality);
}
public void testFunctionModalityInTrait(String classWithFunction, Modality expectedModality) {
testFunctionModality(classWithFunction, ClassKind.TRAIT, expectedModality);
}
public void testPropertyModalityInClass(String classWithProperty, Modality expectedModality) {
testPropertyModality(classWithProperty, ClassKind.CLASS, expectedModality);
}
public void testPropertyModalityInEnum(String classWithProperty, Modality expectedModality) {
testPropertyModality(classWithProperty, ClassKind.ENUM_CLASS, expectedModality);
}
public void testPropertyModalityInTrait(String classWithProperty, Modality expectedModality) {
testPropertyModality(classWithProperty, ClassKind.TRAIT, expectedModality);
}
public void testPropertyAccessorModalityInClass(String classWithPropertyWithAccessor, Modality expectedModality) {
testPropertyAccessorModality(classWithPropertyWithAccessor, ClassKind.CLASS, expectedModality, true);
}
public void testPropertyAccessorModalityInTrait(String classWithPropertyWithAccessor, Modality expectedModality) {
testPropertyAccessorModality(classWithPropertyWithAccessor, ClassKind.TRAIT, expectedModality, true);
}
public void testPropertyAccessorModalityInClass(String classWithPropertyWithAccessor, Modality expectedModality, boolean isGetter) {
testPropertyAccessorModality(classWithPropertyWithAccessor, ClassKind.CLASS, expectedModality, isGetter);
}
public void testPropertyAccessorModalityInTrait(String classWithPropertyWithAccessor, Modality expectedModality, boolean isGetter) {
testPropertyAccessorModality(classWithPropertyWithAccessor, ClassKind.TRAIT, expectedModality, isGetter);
}
}
public void testClassModality() {
tc.testClassModality("class A {}", Modality.FINAL);
tc.testClassModality("open class A {}", Modality.OPEN);
tc.testClassModality("abstract class A {}", Modality.ABSTRACT);
tc.testClassModality("final class A {}", Modality.FINAL);
tc.testClassModality("open abstract class A {}", Modality.ABSTRACT);
tc.testEnumModality("enum class A {}", Modality.FINAL);
tc.testEnumModality("open enum class A {}", Modality.OPEN);
tc.testEnumModality("abstract enum class A {}", Modality.ABSTRACT);
tc.testEnumModality("final enum class A {}", Modality.FINAL);
tc.testTraitModality("trait A {}", Modality.ABSTRACT);
tc.testTraitModality("open trait A {}", Modality.ABSTRACT);
tc.testTraitModality("abstract trait A {}", Modality.ABSTRACT);
}
public void testFunctionModality() {
tc.testFunctionModalityInClass("class A { fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInClass("class A { open fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInClass("class A { final fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInClass("open class A { fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInClass("open class A { open fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInClass("open class A { final fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInClass("abstract class A { open fun foo() }", Modality.OPEN);
tc.testFunctionModalityInClass("abstract class A { abstract fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInEnum("enum class A { fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInEnum("enum class A { final fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInEnum("open enum class A { open fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInEnum("abstract enum class A { open fun foo() }", Modality.OPEN);
tc.testFunctionModalityInEnum("abstract enum class A { abstract fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInTrait("trait A { fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInTrait("trait A { abstract fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInTrait("trait A { fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInTrait("trait A { open fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInTrait("trait A { final fun foo() {} }", Modality.FINAL);
}
public void testFunctionModalityWithOverride() {
tc.testFunctionModalityInClass("class A : C { override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInClass("class A : C { open override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInClass("class A : C { final override fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInClass("open class A : C { override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInClass("open class A : C { open override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInClass("open class A : C { final override fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInClass("abstract class A : C { open override fun foo() }", Modality.OPEN);
tc.testFunctionModalityInClass("abstract class A : C { abstract override fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInEnum("enum class A : C { override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInEnum("enum class A : C { final override fun foo() {} }", Modality.FINAL);
tc.testFunctionModalityInEnum("open enum class A : C { open override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInEnum("abstract enum class A : C { open override fun foo() }", Modality.OPEN);
tc.testFunctionModalityInEnum("abstract enum class A : C { abstract override fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInTrait("trait A : C { override fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInTrait("trait A : C { abstract override fun foo() }", Modality.ABSTRACT);
tc.testFunctionModalityInTrait("trait A : C { override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInTrait("trait A : C { open override fun foo() {} }", Modality.OPEN);
tc.testFunctionModalityInTrait("trait A : C { final override fun foo() {} }", Modality.FINAL);
}
public void testPropertyModality() {
tc.testPropertyModalityInClass("class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("class A { final val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("open class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("open class A { final val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("open class A { open val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("abstract class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("abstract class A { open val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("abstract class A { abstract val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInEnum("enum class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInEnum("enum class A { final val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInEnum("open enum class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInEnum("open enum class A { final val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInEnum("open enum class A { open val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInEnum("abstract enum class A { open val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInEnum("abstract enum class A { abstract val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { open val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { abstract val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { open abstract val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { val a: Int get() = 10 }", Modality.OPEN);
tc.testPropertyModalityInTrait("trait A { var a: Int get() = 1; set(v: Int) {} }", Modality.OPEN);
tc.testPropertyModalityInTrait("trait A { val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { var a: Int open get open set}", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { open val a: Int get }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A { open val a: Int get() = 1 }", Modality.OPEN);
tc.testPropertyModalityInTrait("trait A { open val a: Int final get() = 1 }", Modality.OPEN);
}
public void testPropertyModalityWithOverride() {
tc.testPropertyModalityInClass("class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("class A : C { final override val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("open class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("open class A : C { final override val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInClass("open class A : C { open override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("abstract class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("abstract class A : C { open override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInClass("abstract class A : C { abstract override val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInEnum("enum class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInEnum("enum class A : C { final override val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInEnum("open enum class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInEnum("open enum class A : C { final override val a: Int = 0 }", Modality.FINAL);
tc.testPropertyModalityInEnum("open enum class A : C { open override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInEnum("abstract enum class A : C { open override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyModalityInEnum("abstract enum class A : C { abstract override val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { override val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { open override val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { abstract override val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { open abstract override val a: Int }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { override val a: Int get() = 10 }", Modality.OPEN);
tc.testPropertyModalityInTrait("trait A : C { override var a: Int get() = 1; set(v: Int) {} }", Modality.OPEN);
tc.testPropertyModalityInTrait("trait A : C { override val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { override var a: Int open get open set }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { open override val a: Int get }", Modality.ABSTRACT);
tc.testPropertyModalityInTrait("trait A : C { open override val a: Int get() = 1 }", Modality.OPEN);
tc.testPropertyModalityInTrait("trait A : C { open override val a: Int final get() = 1 }", Modality.OPEN);
}
public void testPropertyAccessorModality() {
tc.testPropertyAccessorModalityInClass("class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A { val a: Int = 0; get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A { val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A { final val a: Int = 0 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A { final val a: Int = 0; get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A { final val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { val a: Int = 0 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { val a: Int = 0; get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { open val a: Int = 0 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A { open val a: Int = 0; get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A { open val a: Int = 0; open get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A { open val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { final val a: Int = 0 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { final val a: Int = 0; get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A { final val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("abstract class A { abstract val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { abstract val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { abstract val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { abstract val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { val a: Int get() = 10 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("abstract class A { val a: Int open get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A { val a: Int final get() = 10 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("abstract class A { open abstract val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { open abstract val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { open abstract val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { open abstract val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A { open val a: Int get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A { open val a: Int open get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A { open val a: Int final get() = 10 }", Modality.FINAL);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int open get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInTrait("trait A { val a: Int final get() = 1 }", Modality.FINAL);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int open get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInTrait("abstract trait A { val a: Int final get() = 1 }", Modality.FINAL);
}
public void testPropertyAccessorModalityWithOverride() {
tc.testPropertyAccessorModalityInClass("class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("class A : C { override val a: Int = 0; get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("class A : C { override val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A : C { final override val a: Int = 0 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A : C { final override val a: Int = 0; get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A : C { final override val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("class A : C { final override val a: Int = 0; override get() = 2 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { override val a: Int = 0; get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { override val a: Int = 0; open get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { override val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { override val a: Int = 0; override get() = 2 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { override val a: Int = 0; final override get() = 2 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { open override val a: Int = 0 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { open override val a: Int = 0; get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { open override val a: Int = 0; open get }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { open override val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { open override val a: Int = 0; override get() = 2 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { open override val a: Int = 0; final override get() = 2 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { final override val a: Int = 0 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { final override val a: Int = 0; get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { final override val a: Int = 0; final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("open class A : C { final override val a: Int = 0; override get() = 2 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("open class A : C { final override val a: Int = 0; final override get() = 2 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("abstract class A : C { abstract override val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { abstract override val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { abstract override val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { abstract override val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { override val a: Int override get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A : C { override val a: Int open override get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A : C { override val a: Int final override get() = 10 }", Modality.FINAL);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open abstract override val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open abstract override val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open abstract override val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open abstract override val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open override val a: Int override get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open override val a: Int open override get() = 10 }", Modality.OPEN);
tc.testPropertyAccessorModalityInClass("abstract class A : C { open override val a: Int final override get() = 10 }", Modality.FINAL);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int override get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int abstract get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int open get }", Modality.ABSTRACT);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int open override get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int override get() = 1 }", Modality.OPEN);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int final get }", Modality.FINAL);
tc.testPropertyAccessorModalityInTrait("trait A : C { override val a: Int final override get() = 1 }", Modality.FINAL);
}
}
@@ -0,0 +1,150 @@
package org.jetbrains.jet.types;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.PathManager;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.File;
/**
* @author abreslav
*/
public class JetOverridingTest extends LightDaemonAnalyzerTestCase {
private ModuleDescriptor root = new ModuleDescriptor("test_root");
private JetStandardLibrary library;
private JetSemanticServices semanticServices;
private ClassDescriptorResolver classDescriptorResolver;
@Override
public void setUp() throws Exception {
super.setUp();
library = JetStandardLibrary.getJetStandardLibrary(getProject());
semanticServices = JetSemanticServices.createSemanticServices(library);
classDescriptorResolver = semanticServices.getClassDescriptorResolver(JetTestUtils.DUMMY_TRACE);
}
@Override
protected String getTestDataPath() {
return getHomeDirectory() + "/compiler/testData";
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
}
public void testBasic() throws Exception {
assertOverridable(
"fun a() : Int",
"fun a() : Int");
assertOverridable(
"fun a<T1>() : T1",
"fun a<T>() : T");
assertOverridable(
"fun a<T1>(a : T1) : T1",
"fun a<T>(a : T) : T");
assertOverridable(
"fun a<T1, X : T1>(a : T1) : T1",
"fun a<T, Y : T>(a : T) : T");
assertOverridable(
"fun a<T1, X : T1>(a : T1) : T1",
"fun a<T, Y : T>(a : T) : Y");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
assertNotOverridable(
"fun ab() : Int",
"fun a() : Int");
assertOverridable(
"fun a() : Int",
"fun a() : Any");
assertNotOverridable(
"fun a(a : Int) : Int",
"fun a() : Int");
assertNotOverridable(
"fun a() : Int",
"fun a(a : Int) : Int");
assertNotOverridable(
"fun a(a : Int?) : Int",
"fun a(a : Int) : Int");
assertNotOverridable(
"fun a<T>(a : Int) : Int",
"fun a(a : Int) : Int");
assertNotOverridable(
"fun a<T1, X : T1>(a : T1) : T1",
"fun a<T, Y>(a : T) : T");
assertNotOverridable(
"fun a<T1, X : T1>(a : T1) : T1",
"fun a<T, Y : T>(a : Y) : T");
assertOverridable(
"fun a<T1, X : T1>(a : T1) : X",
"fun a<T, Y : T>(a : T) : T");
assertOverridable(
"fun a<T1, X : Array<out T1>>(a : Array<in T1>) : T1",
"fun a<T, Y : Array<out T>>(a : Array<in T>) : T");
assertNotOverridable(
"fun a<T1, X : Array<T1>>(a : Array<in T1>) : T1",
"fun a<T, Y : Array<out T>>(a : Array<in T>) : T");
assertNotOverridable(
"fun a<T1, X : Array<out T1>>(a : Array<in T1>) : T1",
"fun a<T, Y : Array<in T>>(a : Array<in T>) : T");
assertNotOverridable(
"fun a<T1, X : Array<out T1>>(a : Array<in T1>) : T1",
"fun a<T, Y : Array<*>>(a : Array<in T>) : T");
assertNotOverridable(
"fun a<T1, X : Array<out T1>>(a : Array<in T1>) : T1",
"fun a<T, Y : Array<out T>>(a : Array<out T>) : T");
assertNotOverridable(
"fun a<T1, X : Array<out T1>>(a : Array<*>) : T1",
"fun a<T, Y : Array<out T>>(a : Array<in T>) : T");
}
private void assertOverridable(String superFun, String subFun) {
assertOverridabilityRelation(superFun, subFun, false);
}
private void assertNotOverridable(String superFun, String subFun) {
assertOverridabilityRelation(superFun, subFun, true);
}
private void assertOverridabilityRelation(String superFun, String subFun, boolean expectedIsError) {
FunctionDescriptor a = makeFunction(superFun);
FunctionDescriptor b = makeFunction(subFun);
OverridingUtil.OverrideCompatibilityInfo overridableWith = OverridingUtil.isOverridableBy(a, b);
assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isSuccess());
}
private FunctionDescriptor makeFunction(String funDecl) {
JetNamedFunction function = JetPsiFactory.createFunction(getProject(), funDecl);
return classDescriptorResolver.resolveFunctionDescriptor(root, library.getLibraryScope(), function);
}
}
@@ -0,0 +1,711 @@
package org.jetbrains.jet.types;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetTestCaseBase;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.File;
import java.util.*;
/**
* @author abreslav
*/
public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
private JetStandardLibrary library;
private JetSemanticServices semanticServices;
private ClassDefinitions classDefinitions;
private ClassDescriptorResolver classDescriptorResolver;
private JetScope scopeWithImports;
private TypeResolver typeResolver;
@Override
public void setUp() throws Exception {
super.setUp();
library = JetStandardLibrary.getJetStandardLibrary(getProject());
semanticServices = JetSemanticServices.createSemanticServices(library);
classDefinitions = new ClassDefinitions();
classDescriptorResolver = semanticServices.getClassDescriptorResolver(JetTestUtils.DUMMY_TRACE);
scopeWithImports = addImports(classDefinitions.BASIC_SCOPE);
typeResolver = new TypeResolver(semanticServices, JetTestUtils.DUMMY_TRACE, true);
}
@Override
protected String getTestDataPath() {
return getHomeDirectory() + "/compiler/testData";
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
}
public void testConstants() throws Exception {
assertType("1", library.getIntType());
assertType("0x1", library.getIntType());
assertType("0X1", library.getIntType());
assertType("0b1", library.getIntType());
assertType("0B1", library.getIntType());
assertType("1.lng", library.getLongType());
assertType("1.0", library.getDoubleType());
assertType("1.0.dbl", library.getDoubleType());
assertType("0x1.fffffffffffffp1023", library.getDoubleType());
assertType("1.0.flt", library.getFloatType());
assertType("0x1.fffffffffffffp1023.flt", library.getFloatType());
assertType("true", library.getBooleanType());
assertType("false", library.getBooleanType());
assertType("'d'", library.getCharType());
assertType("\"d\"", library.getStringType());
assertType("\"\"\"d\"\"\"", library.getStringType());
assertType("()", JetStandardClasses.getUnitType());
assertType("null", JetStandardClasses.getNullableNothingType());
}
public void testTupleConstants() throws Exception {
assertType("()", JetStandardClasses.getUnitType());
assertType("(1, 'a')", JetStandardClasses.getTupleType(library.getIntType(), library.getCharType()));
}
public void testTypeInfo() throws Exception {
assertType("typeinfo.typeinfo<Int>", "typeinfo.TypeInfo<Int>");
assertType("typeinfo.typeinfo<typeinfo.TypeInfo<Int>>", "typeinfo.TypeInfo<typeinfo.TypeInfo<Int>>");
}
public void testJumps() throws Exception {
assertType("throw java.lang.Exception()", JetStandardClasses.getNothingType());
assertType("continue", JetStandardClasses.getNothingType());
assertType("break", JetStandardClasses.getNothingType());
}
public void testIf() throws Exception {
assertType("if (true) 1", "Unit");
assertType("if (true) 1 else 1", "Int");
assertType("if (true) 1 else return", "Int");
assertType("if (true) return else 1", "Int");
assertType("if (true) throw Exception() else throw Exception()", "Nothing");
assertType("if (true) 1 else null", "Int?");
assertType("if (true) null else null", "Nothing?");
assertType("if (true) 1 else '1'", "Any");
assertType("if (true) else '1'", "Unit");
assertType("if (true) else a = 0", "Unit");
}
public void testWhen() throws Exception {
assertType("when (1) { is 1 => 2; } ", "Int");
assertType("when (1) { is 1 => 2; is 1 => '2'} ", "Any");
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 => null} ", "Any?");
assertType("when (1) { is 1 => 2; is 1 => '2'; else => null} ", "Any?");
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 => when(2) {is 1 => null}} ", "Any?");
}
public void testTry() throws Exception {
assertType("try {1} finally{2}", "Int");
assertType("try {1} catch (e : Exception) {'a'} finally{2}", "Int");
assertType("try {1} catch (e : Exception) {'a'} finally{'2'}", "Any");
assertType("try {1} catch (e : Exception) {'a'}", "Any");
assertType("try {1} catch (e : Exception) {'a'} catch (e : Exception) {null}", "Any?");
assertType("try {} catch (e : Exception) {}", "Unit");
}
public void testCommonSupertypes() throws Exception {
assertCommonSupertype("Int", "Int", "Int");
assertCommonSupertype("Int", "Int", "Nothing");
assertCommonSupertype("Int", "Nothing", "Int");
assertCommonSupertype("Nothing", "Nothing", "Nothing");
assertCommonSupertype("Int?", "Int", "Nothing?");
assertCommonSupertype("Nothing?", "Nothing?", "Nothing?");
assertCommonSupertype("Any", "Int", "Char");
assertCommonSupertype("Base_T<*>", "Base_T<*>", "Derived_T<*>");
assertCommonSupertype("Any", "Base_inT<*>", "Derived_T<*>");
assertCommonSupertype("Derived_T<Int>", "DDerived_T<Int>", "Derived_T<Int>");
assertCommonSupertype("Derived_T<Int>", "DDerived_T<Int>", "DDerived1_T<Int>");
assertCommonSupertype("Comparable<*>", "Comparable<Int>", "Comparable<Boolean>");
assertCommonSupertype("Base_T<out Comparable<*>>", "Base_T<Int>", "Base_T<Boolean>");
assertCommonSupertype("Base_T<in Int>", "Base_T<Int>", "Base_T<in Int>");
assertCommonSupertype("Base_T<in Int>", "Derived_T<Int>", "Base_T<in Int>");
assertCommonSupertype("Base_T<in Int>", "Derived_T<in Int>", "Base_T<Int>");
assertCommonSupertype("Base_T<*>", "Base_T<Int>", "Base_T<*>");
}
public void testIntersect() throws Exception {
assertIntersection("Int?", "Int?", "Int?");
assertIntersection("Int", "Int?", "Int");
assertIntersection("Int", "Int", "Int?");
}
public void testBasicSubtyping() throws Exception {
assertSubtype("Boolean", "Boolean");
assertSubtype("Byte", "Byte");
assertSubtype("Char", "Char");
assertSubtype("Short", "Short");
assertSubtype("Int", "Int");
assertSubtype("Long", "Long");
assertSubtype("Float", "Float");
assertSubtype("Double", "Double");
assertSubtype("Unit", "Unit");
assertSubtype("Boolean", "Any");
assertSubtype("Byte", "Any");
assertSubtype("Char", "Any");
assertSubtype("Short", "Any");
assertSubtype("Int", "Any");
assertSubtype("Long", "Any");
assertSubtype("Float", "Any");
assertSubtype("Double", "Any");
assertSubtype("Unit", "Any");
assertSubtype("Any", "Any");
assertNotSubtype("Boolean", "Byte");
assertNotSubtype("Byte", "Short");
assertNotSubtype("Char", "Int");
assertNotSubtype("Short", "Int");
assertNotSubtype("Int", "Long");
assertNotSubtype("Long", "Double");
assertNotSubtype("Float", "Double");
assertNotSubtype("Double", "Int");
assertNotSubtype("Unit", "Int");
}
public void testTuples() throws Exception {
assertSubtype("Unit", "()");
assertSubtype("()", "Unit");
assertSubtype("()", "()");
assertSubtype("(Boolean)", "(Boolean)");
assertSubtype("(Byte)", "(Byte)");
assertSubtype("(Char)", "(Char)");
assertSubtype("(Short)", "(Short)");
assertSubtype("(Int)", "(Int)");
assertSubtype("(Long)", "(Long)");
assertSubtype("(Float)", "(Float)");
assertSubtype("(Double)", "(Double)");
assertSubtype("(Unit)", "(Unit)");
assertSubtype("(Unit, Unit)", "(Unit, Unit)");
assertSubtype("(Boolean)", "(Boolean)");
assertSubtype("(Byte)", "(Byte)");
assertSubtype("(Char)", "(Char)");
assertSubtype("(Short)", "(Short)");
assertSubtype("(Int)", "(Int)");
assertSubtype("(Long)", "(Long)");
assertSubtype("(Float)", "(Float)");
assertSubtype("(Double)", "(Double)");
assertSubtype("(Unit)", "(Unit)");
assertSubtype("(Unit, Unit)", "(Unit, Unit)");
assertNotSubtype("(Unit)", "(Int)");
assertSubtype("(Unit)", "(Any)");
assertSubtype("(Unit, Unit)", "(Any, Any)");
assertSubtype("(Unit, Unit)", "(Any, Unit)");
assertSubtype("(Unit, Unit)", "(Unit, Any)");
}
public void testProjections() throws Exception {
assertSubtype("Base_T<Int>", "Base_T<Int>");
assertNotSubtype("Base_T<Int>", "Base_T<Any>");
assertSubtype("Base_inT<Int>", "Base_inT<Int>");
assertSubtype("Base_inT<Any>", "Base_inT<Int>");
assertNotSubtype("Base_inT<Int>", "Base_inT<Any>");
assertSubtype("Base_outT<Int>", "Base_outT<Int>");
assertSubtype("Base_outT<Int>", "Base_outT<Any>");
assertNotSubtype("Base_outT<Any>", "Base_outT<Int>");
assertSubtype("Base_T<Int>", "Base_T<out Any>");
assertSubtype("Base_T<Any>", "Base_T<in Int>");
assertSubtype("Base_T<out Int>", "Base_T<out Int>");
assertSubtype("Base_T<in Int>", "Base_T<in Int>");
assertSubtype("Base_inT<out Int>", "Base_inT<out Int>");
assertSubtype("Base_inT<in Int>", "Base_inT<in Int>");
assertSubtype("Base_outT<out Int>", "Base_outT<out Int>");
assertSubtype("Base_outT<in Int>", "Base_outT<in Int>");
assertSubtype("Base_T<Int>", "Base_T<*>");
assertSubtype("Base_T<*>", "Base_T<*>");
assertSubtype("Base_T<Int>", "Base_T<out Any>");
assertSubtype("Base_T<Any>", "Base_T<in Int>");
assertNotSubtype("Base_T<out Any>", "Base_T<in Int>");
assertNotSubtype("Base_T<in Int>", "Base_T<out Int>");
assertNotSubtype("Base_T<*>", "Base_T<out Int>");
assertSubtype("Derived_T<Int>", "Base_T<Int>");
assertSubtype("Derived_outT<Int>", "Base_outT<Int>");
assertSubtype("Derived_inT<Int>", "Base_inT<Int>");
assertSubtype("Derived_T<*>", "Base_T<*>");
assertNotSubtype("Derived_T<Int>", "Base_T<Any>");
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
assertSubtype("Derived_T<Any>", "Base_T<in Int>");
assertSubtype("Derived_T<Int>", "Base_T<in Int>");
assertSubtype("MDerived_T<Int>", "Base_T<in Int>");
assertSubtype("ArrayList<Int>", "List<in Int>");
// assertSubtype("java.lang.Integer", "java.lang.Comparable<java.lang.Integer>?");
}
public void testNullable() throws Exception {
assertSubtype("Any?", "Any?");
assertSubtype("Any", "Any?");
assertNotSubtype("Any?", "Any");
assertSubtype("Int", "Any?");
assertSubtype("Int?", "Any?");
assertNotSubtype("Int?", "Any");
}
public void testNothing() throws Exception {
assertSubtype("Nothing", "Any");
assertSubtype("Nothing?", "Any?");
assertNotSubtype("Nothing?", "Any");
assertSubtype("Nothing", "Int");
assertSubtype("Nothing?", "Int?");
assertNotSubtype("Nothing?", "Int");
assertSubtype("Nothing?", "Base_T<*>?");
assertSubtype("Nothing?", "Derived_T<*>?");
}
public void testThis() throws Exception {
assertType("Derived_T<Int>", "this", "Derived_T<Int>");
// assertType("Derived_T<Int>", "super<Base_T>", "Base_T<Int>");
}
public void testLoops() throws Exception {
assertType("while (1) {1}", "Unit");
assertType("do {1} while(1)", "Unit");
assertType("for (i in 1) {1}", "Unit");
}
public void testFunctionLiterals() throws Exception {
assertType("{() => }", "fun () : Unit");
assertType("{() : Int => }", "fun () : Int");
assertType("{() => 1}", "fun () : Int");
assertType("{(a : Int) => 1}", "fun (a : Int) : Int");
assertType("{(a : Int, b : String) => 1}", "fun (a : Int, b : String) : Int");
assertType("{(a : Int) => 1}", "fun (Int) : Int");
assertType("{(a : Int, b : String) => 1}", "fun (Int, String) : Int");
assertType("{Any.() => 1}", "fun Any.() : Int");
assertType("{Any.(a : Int) => 1}", "fun Any.(a : Int) : Int");
assertType("{Any.(a : Int, b : String) => 1}", "fun Any.(a : Int, b : String) : Int");
assertType("{Any.(a : Int) => 1}", "fun Any.(Int) : Int");
assertType("{Any.(a : Int, b : String) => 1}", "fun Any.(Int, String) : Int");
assertType("{Any.(a : Int, b : String) => b}", "fun Any.(Int, String) : String");
}
public void testBlocks() throws Exception {
assertType("if (1) {val a = 1; a} else {null}", "Int?");
assertType("if (1) {() => val a = 1; a} else {() => null}", "Function0<Int?>");
assertType("if (1) {() => val a = 1; a; var b : Boolean; b} else null", "Function0<Boolean>?");
assertType("if (1) {() => val a = 1; a; var b = a; b} else null", "Function0<Int>?");
}
public void testNew() throws Exception {
assertType("Base_T<Int>()", "Base_T<Int>");
}
public void testPropertiesInClasses() throws Exception {
assertType("Properties().p", "Int");
assertType("Props<Int>().p", "Int");
assertType("Props<out Int>().p", "Int");
assertType("Props<Properties>().p.p", "Int");
assertType("(return : Props<in Int>).p", "Any?");
}
public void testOverloads() throws Exception {
assertType("Functions<String>().f()", "Unit");
assertType("Functions<String>().f(1)", "Int");
assertType("Functions<Double>().f((1, 1))", "Double");
assertType("Functions<Double>().f(1.0)", "Any");
assertType("Functions<Byte>().f<String>(\"\")", "Byte");
assertType("f()", "Unit");
assertType("f(1)", "Int");
assertType("f(1.flt, 1)", "Float");
assertType("f<String>(1.flt)", "String");
}
public void testPlus() throws Exception {
assertType("1.0.plus(1.dbl)", "Double");
assertType("1.0.plus(1.flt)", "Double");
assertType("1.0.plus(1.lng)", "Double");
assertType("1.0.plus(1)", "Double");
assertType("1.flt.plus(1.dbl)", "Double");
assertType("1.flt.plus(1.flt)", "Float");
assertType("1.flt.plus(1.lng)", "Float");
assertType("1.flt.plus(1)", "Float");
assertType("1.lng.plus(1.dbl)", "Double");
assertType("1.lng.plus(1.flt)", "Float");
assertType("1.lng.plus(1.lng)", "Long");
assertType("1.lng.plus(1)", "Long");
assertType("1.plus(1.dbl)", "Double");
assertType("1.plus(1.flt)", "Float");
assertType("1.plus(1.lng)", "Long");
assertType("1.plus(1)", "Int");
assertType("'1'.plus(1.dbl)", "Double");
assertType("'1'.plus(1.flt)", "Float");
assertType("'1'.plus(1.lng)", "Long");
assertType("'1'.plus(1)", "Int");
assertType("'1'.plus('1')", "Int");
assertType("(1:Short).plus(1.dbl)", "Double");
assertType("(1:Short).plus(1.flt)", "Float");
assertType("(1:Short).plus(1.lng)", "Long");
assertType("(1:Short).plus(1)", "Int");
assertType("(1:Short).plus(1:Short)", "Int");
assertType("(1:Byte).plus(1.dbl)", "Double");
assertType("(1:Byte).plus(1.flt)", "Float");
assertType("(1:Byte).plus(1.lng)", "Long");
assertType("(1:Byte).plus(1)", "Int");
assertType("(1:Byte).plus(1:Short)", "Int");
assertType("(1:Byte).plus(1:Byte)", "Int");
assertType("\"1\".plus(1.dbl)", "String");
assertType("\"1\".plus(1.flt)", "String");
assertType("\"1\".plus(1.lng)", "String");
assertType("\"1\".plus(1)", "String");
assertType("\"1\".plus('1')", "String");
}
public void testBinaryOperations() throws Exception {
assertType("1 as Any", "Any");
assertType("1 is Char", "Boolean");
assertType("1 === null", "Boolean");
assertType("1 !== null", "Boolean");
assertType("true && false", "Boolean");
assertType("true || false", "Boolean");
assertType("null ?: false", "Boolean");
assertType("WithPredicate()?isValid()", "WithPredicate?");
assertType("WithPredicate()?isValid(1)", "WithPredicate?");
assertType("WithPredicate()?p", "WithPredicate?");
}
public void testSupertypes() throws Exception {
assertSupertypes("DDerived1_T<Int>", "Derived_T<Int>", "Base_T<Int>", "Any");
assertSupertypes("DDerived2_T<Int>", "Derived_T<Int>", "Base_T<Int>", "Any");
assertSupertypes("Derived1_inT<Int>", "Derived_T<Int>", "Base_T<Int>", "Any", "Base_inT<Int>");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void assertSupertypes(String typeStr, String... supertypeStrs) {
Set<JetType> allSupertypes = TypeUtils.getAllSupertypes(makeType(scopeWithImports, typeStr));
Set<JetType> expected = Sets.newHashSet();
for (String supertypeStr : supertypeStrs) {
JetType supertype = makeType(scopeWithImports, supertypeStr);
expected.add(supertype);
}
assertEquals(expected, allSupertypes);
}
private void assertSubtype(String subtype, String supertype) {
assertSubtypingRelation(subtype, supertype, true);
}
private void assertNotSubtype(String subtype, String supertype) {
assertSubtypingRelation(subtype, supertype, false);
}
private void assertIntersection(String expected, String... types) {
Set<JetType> typesToIntersect = new LinkedHashSet<JetType>();
for (String type : types) {
typesToIntersect.add(makeType(type));
}
JetType result = TypeUtils.intersect(semanticServices.getTypeChecker(), typesToIntersect);
// assertNotNull("Intersection is null for " + typesToIntersect, result);
assertEquals(makeType(expected), result);
}
private void assertCommonSupertype(String expected, String... types) {
Collection<JetType> subtypes = new ArrayList<JetType>();
for (String type : types) {
subtypes.add(makeType(type));
}
JetType result = semanticServices.getTypeChecker().commonSupertype(subtypes);
assertTrue(result + " != " + expected, result.equals(makeType(expected)));
}
private void assertSubtypingRelation(String subtype, String supertype, boolean expected) {
JetType typeNode1 = makeType(subtype);
JetType typeNode2 = makeType(supertype);
boolean result = semanticServices.getTypeChecker().isSubtypeOf(
typeNode1,
typeNode2);
String modifier = expected ? "not " : "";
assertTrue(typeNode1 + " is " + modifier + "a subtype of " + typeNode2, result == expected);
}
private void assertType(String expression, JetType expectedType) {
Project project = getProject();
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).getType(scopeWithImports, jetExpression, TypeUtils.NO_EXPECTED_TYPE);
assertTrue(type + " != " + expectedType, type.equals(expectedType));
}
private void assertErrorType(String expression) {
Project project = getProject();
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).safeGetType(scopeWithImports, jetExpression, TypeUtils.NO_EXPECTED_TYPE);
assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type));
}
private void assertType(String contextType, final String expression, String expectedType) {
final JetType thisType = makeType(contextType);
JetScope scope = new JetScopeAdapter(classDefinitions.BASIC_SCOPE) {
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
return new ExpressionReceiver(JetPsiFactory.createExpression(getProject(), expression), thisType);
}
};
assertType(scope, expression, expectedType);
}
private void assertType(String expression, String expectedTypeStr) {
assertType(scopeWithImports, expression, expectedTypeStr);
}
private void assertType(JetScope scope, String expression, String expectedTypeStr) {
Project project = getProject();
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).getType(addImports(scope), jetExpression, TypeUtils.NO_EXPECTED_TYPE);
JetType expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr);
assertEquals(expectedType, type);
}
private WritableScopeImpl addImports(JetScope scope) {
WritableScopeImpl writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), RedeclarationHandler.DO_NOTHING);
writableScope.importScope(library.getLibraryScope());
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(getProject(), semanticServices, JetTestUtils.DUMMY_TRACE);
writableScope.importScope(new JavaPackageScope("", null, javaSemanticServices));
writableScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices));
return writableScope;
}
private JetType makeType(String typeStr) {
return makeType(scopeWithImports, typeStr);
}
private JetType makeType(JetScope scope, String typeStr) {
return new TypeResolver(semanticServices, JetTestUtils.DUMMY_TRACE, true).resolveType(scope, JetPsiFactory.createType(getProject(), typeStr));
}
@Override
protected Sdk getProjectJDK() {
return JetTestCaseBase.jdkFromIdeaHome();
}
private class ClassDefinitions {
private Map<String, ClassDescriptor> CLASSES = new HashMap<String, ClassDescriptor>();
private String[] CLASS_DECLARATIONS = {
"open class Base_T<T>()",
"open class Derived_T<T>() : Base_T<T>",
"open class DDerived_T<T>() : Derived_T<T>",
"open class DDerived1_T<T>() : Derived_T<T>",
"open class DDerived2_T<T>() : Derived_T<T>, Base_T<T>",
"open class Base_inT<in T>()",
"open class Derived_inT<in T>() : Base_inT<T>",
"open class Derived1_inT<in T>() : Base_inT<T>, Derived_T<T>",
"open class Base_outT<out T>()",
"open class Derived_outT<out T>() : Base_outT<T>",
"open class MDerived_T<T>() : Base_outT<out T>, Base_T<T>",
"class Properties() { val p : Int }",
"class Props<T>() { val p : T }",
"class Functions<T>() { " +
"fun f() : Unit {} " +
"fun f(a : Int) : Int {} " +
"fun f(a : T) : Any {} " +
"fun f(a : (Int, Int)) : T {} " +
"fun f<E>(a : E) : T {} " +
"}",
"class WithPredicate() { " +
"fun isValid() : Boolean " +
"fun isValid(x : Int) : Boolean " +
"val p : Boolean " +
"}",
"open class List<E>()",
"open class AbstractList<E> : List<E?>",
"open class ArrayList<E>() : Any, AbstractList<E?>, List<E?>"
};
private String[] FUNCTION_DECLARATIONS = {
"fun f() : Unit {}",
"fun f(a : Int) : Int {a}",
"fun f(a : Float, b : Int) : Float {a}",
"fun f<T>(a : Float) : T {a}",
};
public JetScope BASIC_SCOPE = new JetScopeAdapter(library.getLibraryScope()) {
@Override
public ClassifierDescriptor getClassifier(@NotNull String name) {
if (CLASSES.isEmpty()) {
for (String classDeclaration : CLASS_DECLARATIONS) {
JetClass classElement = JetPsiFactory.createClass(getProject(), classDeclaration);
ClassDescriptor classDescriptor = resolveClassDescriptor(this, classElement);
CLASSES.put(classDescriptor.getName(), classDescriptor);
}
}
ClassDescriptor classDescriptor = CLASSES.get(name);
if (classDescriptor != null) {
return classDescriptor;
}
return super.getClassifier(name);
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
Set<FunctionDescriptor> writableFunctionGroup = Sets.newLinkedHashSet();
ModuleDescriptor module = new ModuleDescriptor("TypeCheckerTest");
for (String funDecl : FUNCTION_DECLARATIONS) {
FunctionDescriptor functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(module, this, JetPsiFactory.createFunction(getProject(), funDecl));
if (name.equals(functionDescriptor.getName())) {
writableFunctionGroup.add(functionDescriptor);
}
}
return writableFunctionGroup;
}
};
@Nullable
public ClassDescriptor resolveClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement) {
final ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
scope.getContainingDeclaration(),
Collections.<AnnotationDescriptor>emptyList(),
JetPsiUtil.safeName(classElement.getName()));
BindingTrace trace = JetTestUtils.DUMMY_TRACE;
trace.record(BindingContext.CLASS, classElement, classDescriptor);
final WritableScope parameterScope = new WritableScopeImpl(scope, classDescriptor, new TraceBasedRedeclarationHandler(trace));
// This call has side-effects on the parameterScope (fills it in)
List<TypeParameterDescriptor> typeParameters
= classDescriptorResolver.resolveTypeParameters(classDescriptor, parameterScope, classElement.getTypeParameters());
classDescriptorResolver.resolveGenericBounds(classElement, parameterScope, typeParameters);
List<JetDelegationSpecifier> delegationSpecifiers = classElement.getDelegationSpecifiers();
// TODO : assuming that the hierarchy is acyclic
Collection<JetType> supertypes = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: classDescriptorResolver.resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
// for (JetType supertype: supertypes) {
// if (supertype.getConstructor().isSealed()) {
// trace.getErrorHandler().genericError(classElement.getNameAsDeclaration().getNode(), "Class " + classElement.getName() + " can not extend final type " + supertype);
// }
// }
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
final WritableScope memberDeclarations = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, new TraceBasedRedeclarationHandler(trace));
List<JetDeclaration> declarations = classElement.getDeclarations();
for (JetDeclaration declaration : declarations) {
declaration.accept(new JetVisitorVoid() {
@Override
public void visitProperty(JetProperty property) {
if (property.getPropertyTypeRef() != null) {
memberDeclarations.addVariableDescriptor(classDescriptorResolver.resolvePropertyDescriptor(classDescriptor, parameterScope, property));
} else {
// TODO : Caution: a cyclic dependency possible
throw new UnsupportedOperationException();
}
}
@Override
public void visitNamedFunction(JetNamedFunction function) {
if (function.getReturnTypeRef() != null) {
memberDeclarations.addFunctionDescriptor(classDescriptorResolver.resolveFunctionDescriptor(classDescriptor, parameterScope, function));
} else {
// TODO : Caution: a cyclic dependency possible
throw new UnsupportedOperationException();
}
}
@Override
public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException(element.toString());
}
});
}
Set<FunctionDescriptor> constructors = Sets.newLinkedHashSet();
classDescriptor.initialize(
!open,
typeParameters,
supertypes,
memberDeclarations,
constructors,
null
);
for (JetConstructor constructor : classElement.getSecondaryConstructors()) {
ConstructorDescriptorImpl functionDescriptor = classDescriptorResolver.resolveSecondaryConstructorDescriptor(memberDeclarations, classDescriptor, constructor);
functionDescriptor.setReturnType(classDescriptor.getDefaultType());
constructors.add(functionDescriptor);
}
ConstructorDescriptorImpl primaryConstructorDescriptor = classDescriptorResolver.resolvePrimaryConstructorDescriptor(scope, classDescriptor, classElement);
if (primaryConstructorDescriptor != null) {
primaryConstructorDescriptor.setReturnType(classDescriptor.getDefaultType());
constructors.add(primaryConstructorDescriptor);
classDescriptor.setPrimaryConstructor(primaryConstructorDescriptor);
}
return classDescriptor;
}
}
}