separate compiler and plugin tests
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user