From bf54dc54535569736683556980bba81aeb8f28b0 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 6 Dec 2011 23:25:26 +0400 Subject: [PATCH 01/20] test nullable return types are read from .class files --- .../resolve/java/JavaDescriptorResolver.java | 26 ++++++++++++++++++- .../testData/readClass/ReturnTypeNotNull.kt | 3 +++ .../testData/readClass/ReturnTypeNullable.kt | 3 +++ .../org/jetbrains/jet/ReadClassDataTest.java | 5 ++-- 4 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/readClass/ReturnTypeNotNull.kt create mode 100644 compiler/testData/readClass/ReturnTypeNullable.kt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 7b581578eb0..4ce838b3069 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -479,7 +479,7 @@ public class JavaDescriptorResolver { DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), typeParameters, semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters), - semanticServices.getTypeTransformer().transformToType(returnType), + semanticServices.getDescriptorResolver().makeReturnType(returnType, method), Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)), resolveVisibilityFromPsiModifiers(method) ); @@ -491,6 +491,30 @@ public class JavaDescriptorResolver { return substitutedFunctionDescriptor; } + private JetType makeReturnType(PsiType returnType, PsiMethod method) { + boolean changeNullable = false; + boolean nullable = true; + + for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { + if (annotation.getQualifiedName().equals("jet.typeinfo.JetMethod")) { + PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullableReturnType"); + if (nullableExpression != null) { + nullable = (Boolean) nullableExpression.getValue(); + } else { + // default value of parameter + nullable = false; + changeNullable = true; + } + } + } + JetType transformedType = semanticServices.getTypeTransformer().transformToType(returnType); + if (changeNullable) { + return TypeUtils.makeNullableAsSpecified(transformedType, nullable); + } else { + return transformedType; + } + } + private static Visibility resolveVisibilityFromPsiModifiers(PsiModifierListOwner modifierListOwner) { //TODO report error return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC : diff --git a/compiler/testData/readClass/ReturnTypeNotNull.kt b/compiler/testData/readClass/ReturnTypeNotNull.kt new file mode 100644 index 00000000000..0e025241a22 --- /dev/null +++ b/compiler/testData/readClass/ReturnTypeNotNull.kt @@ -0,0 +1,3 @@ +namespace test + +fun ff(): String = "" diff --git a/compiler/testData/readClass/ReturnTypeNullable.kt b/compiler/testData/readClass/ReturnTypeNullable.kt new file mode 100644 index 00000000000..6b3e33f7136 --- /dev/null +++ b/compiler/testData/readClass/ReturnTypeNullable.kt @@ -0,0 +1,3 @@ +namespace test + +fun ff(): String? = "" diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java index b476555280e..e97ad3202cd 100644 --- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -105,8 +105,6 @@ public class ReadClassDataTest extends UsefulTestCase { @Override public void runTest() throws Exception { - if (true) return; - createMockCoreEnvironment(); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); @@ -184,7 +182,8 @@ public class ReadClassDataTest extends UsefulTestCase { for (int i = 0; i < a.getValueParameters().size(); ++i) { compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i)); } - System.out.println("function " + a.getName()); + Assert.assertEquals(a.getReturnType(), b.getReturnType()); + System.out.println("fun " + a.getName() + "(...): " + a.getReturnType()); } private void compareAnything(Class clazz, T a, T b) { From e5c39df519c967bff4d9b8cf3f562f6ff57555eb Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 7 Dec 2011 12:19:50 +0400 Subject: [PATCH 02/20] KT-658 Show types in IDEA auto assist for kotlin --- .../resolve/java/JavaDescriptorResolver.java | 2 +- .../lang/resolve/java/JavaPackageScope.java | 49 ++++++++++++-- .../resolve/scopes/WriteThroughScope.java | 4 ++ .../jetbrains/jet/plugin/JetIconProvider.java | 18 +++--- .../compiler/WholeProjectAnalyzerFacade.java | 18 ++++-- idea/testData/completion/basic/FromImports.kt | 9 +++ idea/testData/completion/basic/JavaPackage.kt | 6 ++ .../completion/basic/VariableClassName.kt | 4 +- .../completion/keywords/InTypeScope.kt | 2 +- idea/testData/completion/keywords/TopScope.kt | 10 +-- .../completion/JetBasicCompletionTest.java | 2 +- .../jet/completion/JetCompletionTestBase.java | 64 +++++++++---------- .../completion/KeywordsCompletionTest.java | 8 ++- 13 files changed, 129 insertions(+), 67 deletions(-) create mode 100644 idea/testData/completion/basic/FromImports.kt create mode 100644 idea/testData/completion/basic/JavaPackage.kt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 4ce838b3069..56b9f16b534 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -267,7 +267,7 @@ public class JavaDescriptorResolver { return javaFacade.findClass(qualifiedName, javaSearchScope); } - private PsiPackage findPackage(String qualifiedName) { + /*package*/ PsiPackage findPackage(String qualifiedName) { return javaFacade.findPackage(qualifiedName); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index 776e5219dfc..2763af7e1f4 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -1,10 +1,17 @@ package org.jetbrains.jet.lang.resolve.java; +import com.google.common.collect.Sets; import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiPackage; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl; +import java.util.Collection; import java.util.Collections; import java.util.Set; @@ -14,11 +21,13 @@ import java.util.Set; public class JavaPackageScope extends JetScopeImpl { private final JavaSemanticServices semanticServices; private final DeclarationDescriptor containingDescriptor; - private final String packagePrefix; + private final String packageFQN; + + private Collection allDescriptors; public JavaPackageScope(@NotNull String packageFQN, DeclarationDescriptor containingDescriptor, JavaSemanticServices semanticServices) { this.semanticServices = semanticServices; - this.packagePrefix = packageFQN.isEmpty() ? "" : packageFQN + "."; + this.packageFQN = packageFQN; this.containingDescriptor = containingDescriptor; } @@ -36,7 +45,7 @@ public class JavaPackageScope extends JetScopeImpl { @Override public Set getFunctions(@NotNull String name) { // TODO: what is GlobalSearchScope - PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(packagePrefix + "namespace"); + PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName("namespace")); if (psiClass == null) { return Collections.emptySet(); } @@ -54,7 +63,35 @@ public class JavaPackageScope extends JetScopeImpl { return containingDescriptor; } - private String getQualifiedName(String name) { - return packagePrefix + name; + @NotNull + @Override + public Collection getAllDescriptors() { + if (allDescriptors == null) { + allDescriptors = Sets.newHashSet(); + + final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN); + + if (javaPackage != null) { + final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver(); + + for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) { + allDescriptors.add(descriptorResolver.resolveNamespace(psiSubPackage.getQualifiedName())); + } + + for (PsiClass psiClass : javaPackage.getClasses()) { + if (psiClass.hasModifierProperty(PsiModifier.PUBLIC)) { + allDescriptors.add(descriptorResolver.resolveClass(psiClass)); + } + } + } + } + + return allDescriptors; } + + private String getQualifiedName(String name) { + return (packageFQN.isEmpty() ? "" : packageFQN + ".") + name; + } + + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java index 5f123dc5a44..7113b9ceaaa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java @@ -199,6 +199,10 @@ public class WriteThroughScope extends WritableScopeWithImports { allDescriptors = Lists.newArrayList(); allDescriptors.addAll(writableWorker.getAllDescriptors()); allDescriptors.addAll(getWorkerScope().getAllDescriptors()); + + for (JetScope imported : getImports()) { + allDescriptors.addAll(imported.getAllDescriptors()); + } } return allDescriptors; } diff --git a/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java b/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java index 3d10d912353..c1a8df88bec 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java @@ -4,7 +4,7 @@ import com.intellij.ide.IconProvider; import com.intellij.openapi.util.Iconable; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.Icons; +import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lexer.JetTokens; @@ -15,21 +15,21 @@ import javax.swing.*; * @author yole */ public class JetIconProvider extends IconProvider { - public static final Icon ICON_FOR_OBJECT = Icons.ANONYMOUS_CLASS_ICON; + public static final Icon ICON_FOR_OBJECT = PlatformIcons.ANONYMOUS_CLASS_ICON; @Override public Icon getIcon(@NotNull PsiElement psiElement, int flags) { if (psiElement instanceof JetNamespace) { - return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? Icons.PACKAGE_OPEN_ICON : Icons.PACKAGE_ICON; + return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON; } if (psiElement instanceof JetNamedFunction) { return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass - ? Icons.METHOD_ICON - : Icons.FUNCTION_ICON; + ? PlatformIcons.METHOD_ICON + : PlatformIcons.FUNCTION_ICON; } if (psiElement instanceof JetClass) { JetClass jetClass = (JetClass) psiElement; - Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? Icons.ENUM_ICON : Icons.CLASS_ICON; + Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? PlatformIcons.ENUM_ICON : PlatformIcons.CLASS_ICON; if (jetClass instanceof JetEnumEntry) { JetEnumEntry enumEntry = (JetEnumEntry) jetClass; if (enumEntry.getPrimaryConstructorParameterList() == null) { @@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider { if (((JetParameter) psiElement).getValOrVarNode() != null) { JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class); if (parameterList != null && parameterList.getParent() instanceof JetClass) { - return Icons.PROPERTY_ICON; + return PlatformIcons.PROPERTY_ICON; } } - return Icons.PARAMETER_ICON; + return PlatformIcons.PARAMETER_ICON; } if (psiElement instanceof JetProperty) { - return Icons.PROPERTY_ICON; + return PlatformIcons.PROPERTY_ICON; } return null; } diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java b/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java index 01d853c9d7d..ec99fa7d3df 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java @@ -24,13 +24,23 @@ import java.util.Set; /** * @author abreslav */ -public class WholeProjectAnalyzerFacade { - public static final Function> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function>() { +public final class WholeProjectAnalyzerFacade { + + /** Forbid creating */ + private WholeProjectAnalyzerFacade() {} + + /** + * Will collect all root-namespaces in all kotlin files in the project. + */ + public static final Function> WHOLE_PROJECT_DECLARATION_PROVIDER = + new Function>() { + @Override public Collection fun(final JetFile rootFile) { final Project project = rootFile.getProject(); final Set namespaces = Sets.newLinkedHashSet(); - ProjectRootManager rootManager = ProjectRootManager.getInstance(project); + final ProjectRootManager rootManager = ProjectRootManager.getInstance(project); + if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) { VirtualFile[] contentRoots = rootManager.getContentRoots(); @@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade { } }; + @NotNull public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) { return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER); } - } diff --git a/idea/testData/completion/basic/FromImports.kt b/idea/testData/completion/basic/FromImports.kt new file mode 100644 index 00000000000..893b30bbadb --- /dev/null +++ b/idea/testData/completion/basic/FromImports.kt @@ -0,0 +1,9 @@ +namespace Tests + +import java.util.* + +fun hello() { + val a = So +} + +// EXIST: SortedSet, SortedMap diff --git a/idea/testData/completion/basic/JavaPackage.kt b/idea/testData/completion/basic/JavaPackage.kt new file mode 100644 index 00000000000..59e1767100b --- /dev/null +++ b/idea/testData/completion/basic/JavaPackage.kt @@ -0,0 +1,6 @@ +namespace Tests + +class A : java. + +// EXIST: lang, util, io +// ABSENT: fun, val, var, namespace diff --git a/idea/testData/completion/basic/VariableClassName.kt b/idea/testData/completion/basic/VariableClassName.kt index 0296a23af4c..38c1068b400 100644 --- a/idea/testData/completion/basic/VariableClassName.kt +++ b/idea/testData/completion/basic/VariableClassName.kt @@ -1,10 +1,10 @@ open class MyClass() { } -class A() : My { +class A() { public fun test() { val a : MyC } } -// EXIST: MyClass \ No newline at end of file +// EXIST: MyClass diff --git a/idea/testData/completion/keywords/InTypeScope.kt b/idea/testData/completion/keywords/InTypeScope.kt index 31f2249d499..c8a490df14c 100644 --- a/idea/testData/completion/keywords/InTypeScope.kt +++ b/idea/testData/completion/keywords/InTypeScope.kt @@ -3,4 +3,4 @@ fun foo() { } // TODO: Move all keywords to absent -// EXPECT: fun, val, var, namespace +// EXIST: fun, val, var, namespace diff --git a/idea/testData/completion/keywords/TopScope.kt b/idea/testData/completion/keywords/TopScope.kt index a151d11e196..308a7710384 100644 --- a/idea/testData/completion/keywords/TopScope.kt +++ b/idea/testData/completion/keywords/TopScope.kt @@ -1,8 +1,8 @@ -// EXPECT: namespace, as, type, class, this, super, val, var, fun, for, null, true -// EXPECT: false, is, in, throw, return, break, continue, object, if, try, else, while -// EXPECT: do, when, trait, This -// EXPECT: import, where, by, get, set, abstract, enum, open, annotation, override, private -// EXPECT: public, internal, protected, catch, out, vararg, inline, finally, final, ref +// EXIST: namespace, as, type, class, this, super, val, var, fun, for, null, true +// EXIST: false, is, in, throw, return, break, continue, object, if, try, else, while +// EXIST: do, when, trait, This +// EXIST: import, where, by, get, set, abstract, enum, open, annotation, override, private +// EXIST: public, internal, protected, catch, out, vararg, inline, finally, final, ref // ABSENT: ?in, new, extends, implements \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 14bc6d16912..995363c1be8 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase { setName("testCompletionExecute"); } - public void testCompletionExecute() { + public void testCompletionExecute() throws Exception { doTest(); } diff --git a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java index c0ff4263210..39372cd71c2 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java +++ b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java @@ -2,70 +2,64 @@ package org.jetbrains.jet.completion; import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; import com.intellij.codeInsight.completion.CompletionType; +import com.intellij.codeInsight.completion.LightCompletionTestCase; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupEx; import com.intellij.codeInsight.lookup.LookupManager; -import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.codeInsight.lookup.impl.LookupImpl; +import com.intellij.openapi.projectRoots.Sdk; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.PluginTestCaseBase; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; /** * @author Nikolay.Krasko */ -public abstract class JetCompletionTestBase extends LightCodeInsightTestCase { +public abstract class JetCompletionTestBase extends LightCompletionTestCase { - protected void doTest() { + private CompletionType type; + + protected void doTest() throws Exception { final String testName = getTestName(false); + + type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC; + configureByFile(testName + ".kt"); - CompletionType completionType = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC; - new CodeCompletionHandlerBase(completionType, false, false, true).invokeCompletion(getProject(), getEditor()); - - LookupEx lookup = LookupManager.getActiveLookup(getEditor()); - assert lookup != null; - - HashSet items = new HashSet(resolveLookups(lookup.getItems())); - - List shouldExist = itemsShouldExist(getFile().getText()); - for (String shouldExistItem : shouldExist) { - assertTrue(String.format("Should contain proposal '%s'.", shouldExistItem), - items.contains(shouldExistItem)); - } - - List shouldAbsent = itemsShouldAbsent(getFile().getText()); - for (String shouldAbsentItem : shouldAbsent) { - assertTrue(String.format("Shouldn't contain proposal '%s'.", shouldAbsentItem), - !items.contains(shouldAbsentItem)); - } + assertContainsItems(itemsShouldExist(getFile().getText())); + assertNotContainItems(itemsShouldAbsent(getFile().getText())); } - - private static List resolveLookups(List items) { - ArrayList result = new ArrayList(items.size()); - for (LookupElement item : items) { - result.add(item.getLookupString()); - } - return result; + @Override + protected Sdk getProjectJDK() { + return PluginTestCaseBase.jdkFromIdeaHome(); + } + + @Override + protected void complete(final int time) { + new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false); + + LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor); + myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY); + myPrefix = lookup == null ? null : lookup.itemPattern(lookup.getItems().get(0)); } @NotNull - private static List itemsShouldExist(String fileText) { + private static String[] itemsShouldExist(String fileText) { return findListWithPrefix("// EXIST:", fileText); } @NotNull - private static List itemsShouldAbsent(String fileText) { + private static String[] itemsShouldAbsent(String fileText) { return findListWithPrefix("// ABSENT:", fileText); } @NotNull - private static List findListWithPrefix(String prefix, String fileText) { + private static String[] findListWithPrefix(String prefix, String fileText) { ArrayList result = new ArrayList(); for (String line : findLinesWithPrefixRemoved(prefix, fileText)) { @@ -76,7 +70,7 @@ public abstract class JetCompletionTestBase extends LightCodeInsightTestCase { } } - return result; + return result.toArray(new String[result.size()]); } @NotNull diff --git a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java index 1df0d5ef2cf..4a0e14d9ed4 100644 --- a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.completion; +import junit.framework.Test; import junit.framework.TestSuite; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBuilder; @@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { setName("testCompletionExecute"); } - public void testCompletionExecute() { + public void testCompletionExecute() throws Exception { doTest(); } @@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { + @NotNull @Override - public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new KeywordsCompletionTest(dataPath, name); } }, suite); return suite; } -} \ No newline at end of file +} From d272979b09e605ced6cba2d10c27177383411309 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 7 Dec 2011 11:51:50 +0200 Subject: [PATCH 03/20] thread ring benchmark and related bug fixes (non null array creation and wrong signature of enclosing class) --- .../jetbrains/jet/codegen/ClosureCodegen.java | 5 +- .../jetbrains/jet/codegen/CodegenContext.java | 34 ++--- .../jet/codegen/ExpressionCodegen.java | 19 +-- .../jet/codegen/GenerationState.java | 2 +- .../codegen/ImplementationBodyCodegen.java | 2 +- .../testData/codegen/classes/nonnullarray.jet | 8 + .../testData/codegen/regressions/kt694.jet | 9 ++ .../jetbrains/jet/codegen/ArrayGenTest.java | 5 + .../jetbrains/jet/codegen/ClassGenTest.java | 6 + examples/src/benchmarks/ThreadRing.java | 137 ++++++++++++++++++ examples/src/benchmarks/ThreadRing.kt | 95 ++++++++++++ 11 files changed, 284 insertions(+), 38 deletions(-) create mode 100644 compiler/testData/codegen/classes/nonnullarray.jet create mode 100644 compiler/testData/codegen/regressions/kt694.jet create mode 100644 examples/src/benchmarks/ThreadRing.java create mode 100644 examples/src/benchmarks/ThreadRing.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 75241d6dc74..085dfb7f5c3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -10,7 +10,6 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetFunctionLiteral; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -100,7 +99,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { generateBridge(name, funDescriptor, fun, cv); captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral()); ClassDescriptor thisDescriptor = context.getThisDescriptor(); - final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName()); + final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType()); if (enclosingType == null) captureThis = false; @@ -164,7 +163,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { Collections.emptyList(), Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.emptySet(), null); - final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this); + final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper()); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); return closureContext.outerWasUsed; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index a5d3447e98c..88ce2d7883b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -104,24 +104,24 @@ public abstract class CodegenContext { return new ClassContext(descriptor, kind, this, typeMapper); } - public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) { - return new AnonymousClassContext(descriptor, kind, this, closure); + public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) { + return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper); } public MethodContext intoFunction(FunctionDescriptor descriptor) { return new MethodContext(descriptor, getContextKind(), this); } - public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) { + public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) { if(descriptor == null) { descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.emptyList(), true) .initialize(Collections.emptyList(), Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC); } - return new ConstructorContext(descriptor, getContextKind(), this); + return new ConstructorContext(descriptor, getContextKind(), this, typeMapper); } - public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen) { - return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName); + public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) { + return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper); } public FrameMap prepareFrame(JetTypeMapper mapper) { @@ -170,12 +170,12 @@ public abstract class CodegenContext { return parentContext != null ? parentContext.lookupInContext(d, v, result) : null; } - public Type enclosingClassType() { + public Type enclosingClassType(JetTypeMapper typeMapper) { CodegenContext cur = getParentContext(); while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) cur = cur.getParentContext(); - return cur == null ? null : Type.getObjectType(cur.getContextDescriptor().getName()); + return cur == null ? null : typeMapper.mapType(((ClassDescriptor)cur.getContextDescriptor()).getDefaultType()); } public int getTypeInfoConstantIndex(JetType type) { @@ -290,8 +290,8 @@ public abstract class CodegenContext { return getParentContext().lookupInContext(d, v, result); } - public Type enclosingClassType() { - return getParentContext().enclosingClassType(); + public Type enclosingClassType(JetTypeMapper typeMapper) { + return getParentContext().enclosingClassType(typeMapper); } @Override @@ -305,10 +305,10 @@ public abstract class CodegenContext { } public static class ConstructorContext extends MethodContext { - public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent) { + public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) { super(contextType, kind, parent); - final Type type = enclosingClassType(); + final Type type = enclosingClassType(typeMapper); outerExpression = type != null ? local1 : null; @@ -323,7 +323,7 @@ public abstract class CodegenContext { public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) { super(contextType, contextKind, parentContext, null); - final Type type = enclosingClassType(); + final Type type = enclosingClassType(typeMapper); outerExpression = type != null ? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false) : null; @@ -341,10 +341,10 @@ public abstract class CodegenContext { } public static class AnonymousClassContext extends CodegenContext { - public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure) { + public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) { super(contextType, contextKind, parentContext, closure); - final Type type = enclosingClassType(); + final Type type = enclosingClassType(typeMapper); outerExpression = type != null ? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false) : null; @@ -364,11 +364,11 @@ public abstract class CodegenContext { public static class ClosureContext extends ReceiverContext { private ClassDescriptor classDescriptor; - public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) { + public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) { super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen); this.classDescriptor = classDescriptor; - final Type type = enclosingClassType(); + final Type type = enclosingClassType(typeMapper); outerExpression = type != null ? StackValue.field(type, internalClassName, "this$0", false) : null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e77bf07342d..9f29c28ce15 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1958,26 +1958,13 @@ public class ExpressionCodegen extends JetVisitor { } else { ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration(); - receiver.put(receiver.type, v); v.anew(type); + v.dup(); // TODO typechecker must verify that we're the outer class of the instance being created //noinspection ConstantConditions - if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { - if(!receiver.type.equals(Type.VOID_TYPE)) { - // class object is in receiver - v.dupX1(); - v.swap(); - } - else { - // this$0 need to be put on stack - v.dup(); - v.load(0, typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION)); - } - } - else { - // regular case - v.dup(); + if(!receiver.type.equals(Type.VOID_TYPE)) { + receiver.put(receiver.type, v); } CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index e83fd50e11e..8ddc2d7f5a1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -140,7 +140,7 @@ public class GenerationState { closure.cv = nameAndVisitor.getSecond(); closure.name = nameAndVisitor.getFirst(); - final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION); + final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, typeMapper); new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index d9a6678e5f2..5a552c69372 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -267,7 +267,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); - CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); + CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper); Method constructorMethod; CallableMethod callableMethod; diff --git a/compiler/testData/codegen/classes/nonnullarray.jet b/compiler/testData/codegen/classes/nonnullarray.jet new file mode 100644 index 00000000000..2e480979e6b --- /dev/null +++ b/compiler/testData/codegen/classes/nonnullarray.jet @@ -0,0 +1,8 @@ +class A() { + class B(val i: Int) { + } + + fun test() = Array (10, { B(it) }) +} + +fun box() = if(A().test()[5].i == 5) "OK" else "fail" diff --git a/compiler/testData/codegen/regressions/kt694.jet b/compiler/testData/codegen/regressions/kt694.jet new file mode 100644 index 00000000000..698558d3642 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt694.jet @@ -0,0 +1,9 @@ +namespace org2 + +enum class Test { + A + B + C +} + +fun box() = Test.A.toString() diff --git a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java index f5e8faf941a..5de65ac38f6 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -286,4 +286,9 @@ public class ArrayGenTest extends CodegenTestCase { // System.out.println(generateToText()); blackBox(); } + + public void testNonNullArray() throws Exception { + blackBoxFile("classes/nonnullarray.jet"); + System.out.println(generateToText()); + } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 1f300ca6406..d588a2b8207 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -1,5 +1,7 @@ package org.jetbrains.jet.codegen; +import org.jetbrains.jet.lang.psi.JetNamespace; + import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -216,6 +218,10 @@ public class ClassGenTest extends CodegenTestCase { blackBoxFile("regressions/kt500.jet"); } + public void testKt694 () throws Exception { + blackBoxFile("regressions/kt694.jet"); + } + public void testKt285 () throws Exception { // blackBoxFile("regressions/kt285.jet"); } diff --git a/examples/src/benchmarks/ThreadRing.java b/examples/src/benchmarks/ThreadRing.java new file mode 100644 index 00000000000..f4ffe660979 --- /dev/null +++ b/examples/src/benchmarks/ThreadRing.java @@ -0,0 +1,137 @@ +/** + * The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by Fabien Le Floc'h + * + * Java implementation of thread-ring benchmark. Best performance is achieved with + * MAX_THREAD=1 as the thread-ring test is bested with only 1 os thread. + * This implementation shows using a simple thread pool solves the thread context + * switch issue. + */ + +import java.util.concurrent.*; + +public class ThreadRing { + private static final int MAX_NODES = 503; + private static final int MAX_THREADS = 503; + + private ExecutorService executor; + private final int N; + + static final CountDownLatch cdl = new CountDownLatch(1); + + public static void main(String[] args) throws InterruptedException { + long start = System.currentTimeMillis(); + int n = 5000000; + try { + n = Integer.parseInt(args[0]); + } catch (Exception e) {} + ThreadRing ring = new ThreadRing(n); + Node node = ring.start(MAX_NODES); + node.sendMessage(new TokenMessage(1,0)); + cdl.await(); + + long total = System.currentTimeMillis() - start; + System.out.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]"); + } + + public ThreadRing(int n) { + N = n; + } + + public Node start(int n) { + Node[] nodes = spawnNodes(n); + connectNodes(n, nodes); + return nodes[0]; + } + + private Node[] spawnNodes(int n) { + executor = Executors.newFixedThreadPool(MAX_THREADS); + Node[] nodes = new Node[n+1]; + for (int i = 0; i < n ; i++) { + nodes[i] = new Node(i+1, null); + } + return nodes; + } + + public void connectNodes(int n, Node[] nodes) { + nodes[n] = nodes[0]; + for (int i=0; i queue = new LinkedBlockingQueue(); + private boolean isActive = false; + private int counter; + + public Node(int id, Node nextNode) { + this.nodeId = id; + this.nextNode = nextNode; + this.counter = 0; + } + + public void connect(Node node) { + this.nextNode = node; + isActive = true; + } + + public void sendMessage(TokenMessage m) { + queue.add(m); + executor.execute(this); + } + + + public void run() { + if (isActive) { + try { + TokenMessage m = queue.take(); + if (m.isStop) { + int nextValue = m.value+1; + if (nextValue == MAX_NODES) { +// System.out.println("last one"); + executor.shutdown(); + cdl.countDown(); + } else { + m.value = nextValue; + nextNode.sendMessage(m); + } + isActive = false; +// System.out.println("ending node "+nodeId); + } else { + if (m.value == N) { + System.out.println(nodeId); + nextNode.sendMessage(new TokenMessage(nodeId, 0, true)); + } else { + m.value = m.value + 1; + nextNode.sendMessage(m); + } + } + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + } +} \ No newline at end of file diff --git a/examples/src/benchmarks/ThreadRing.kt b/examples/src/benchmarks/ThreadRing.kt new file mode 100644 index 00000000000..17547adefdd --- /dev/null +++ b/examples/src/benchmarks/ThreadRing.kt @@ -0,0 +1,95 @@ +namespace threadring + +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +val MAX_NODES = 503 +val MAX_THREADS = 503 + +val cdl = CountDownLatch(1) + +fun main(args: Array) { + val start = System.currentTimeMillis() + var n = 5000000; + try { + n = Integer.parseInt(args[0]); + } catch (e: Throwable) { + } + + val ring = ThreadRing(n) + ring.sendMessage(TokenMessage(1,0,false)) + cdl.await(); + + val total = System.currentTimeMillis() - start + System.out?.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]") +} + +class TokenMessage(val nodeId : Int, value: Int, val isStop: Boolean) : AtomicInteger(value){ +} + +class ThreadRing(val N: Int) { + val executor = Executors.newFixedThreadPool(MAX_THREADS).sure() + + val nodes : Array = Array(MAX_NODES+1, { Node(it+1) }) + + { + connectNodes() + } + + fun connectNodes() { + nodes[nodes.size-1] = nodes[0] + for (i in 0..nodes.size-2) { + nodes[i].connect(nodes[i+1]); + } + } + + fun sendMessage(m : TokenMessage) { + nodes[0].sendMessage(m) + } + class Node(val nodeId : Int) : Runnable { + val queue = LinkedBlockingQueue() + var isActive = false + var nextNode : Node? = null + + fun sendMessage(m: TokenMessage) { + queue.add(m) + executor.execute(this) + } + + fun connect(next: Node) { + nextNode = next + isActive = true + } + + override fun run() { + if(isActive) { + try { + val m = queue.take() + if(m.isStop) { + val nextValue = m.get()+1 + if (nextValue == MAX_NODES) { + executor.shutdown() + cdl.countDown() + } else { + m.set(nextValue) + nextNode.sure().sendMessage(m) + } + isActive = false + } + else { + if (m.get() == N) { + System.out?.println(nodeId); + nextNode.sure().sendMessage(TokenMessage(nodeId, 0, true)); + } else { + m.incrementAndGet() + nextNode.sure().sendMessage(m); + } + } + } + catch(e: InterruptedException) { + e.printStackTrace() + } + } + } + } +} From 2d9424873159ab1dd71bfd9bd25682e9c7e44056 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 7 Dec 2011 11:54:23 +0200 Subject: [PATCH 04/20] accidentally commited not finished test commented --- compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index d588a2b8207..0de47ea91ab 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -219,7 +219,7 @@ public class ClassGenTest extends CodegenTestCase { } public void testKt694 () throws Exception { - blackBoxFile("regressions/kt694.jet"); +// blackBoxFile("regressions/kt694.jet"); } public void testKt285 () throws Exception { From 8bdfafd8c10eddf8503089f89049e3277cfeffbe Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 7 Dec 2011 16:24:49 +0400 Subject: [PATCH 05/20] Test for KT-557 Wrong type inference near sure extension function --- .../testData/diagnostics/tests/regressions/kt557.jet | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/regressions/kt557.jet diff --git a/compiler/testData/diagnostics/tests/regressions/kt557.jet b/compiler/testData/diagnostics/tests/regressions/kt557.jet new file mode 100644 index 00000000000..546965a6064 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/kt557.jet @@ -0,0 +1,9 @@ +// KT-557 Wrong type inference near sure extension function + +fun Array.length() : Int { + return 0; +} + +fun test(array : Array?) { + array?.sure>().length() +} \ No newline at end of file From 40937e438bbbb7887a7e9c1ae46531a9ed2e3c7b Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 7 Dec 2011 17:26:28 +0400 Subject: [PATCH 06/20] KT-762 Wrong highlighting in imports (No errors reported on unresolved imports) --- .../jet/lang/resolve/ImportsResolver.java | 108 ++++++++++++++++++ .../lang/resolve/TypeHierarchyResolver.java | 86 ++------------ .../diagnostics/tests/regressions/kt762.jet | 4 + 3 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java create mode 100644 compiler/testData/diagnostics/tests/regressions/kt762.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java new file mode 100644 index 00000000000..a96ce5d3f4a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -0,0 +1,108 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; + +import java.util.List; + +import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE; +import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED; + +/** + * @author abreslav + */ +public class ImportsResolver { + private final TopDownAnalysisContext context; + + public ImportsResolver(@NotNull TopDownAnalysisContext context) { + this.context = context; + } + + public void processTypeImports() { + for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) { + processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace)); + } + } + + private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) { + context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope); + + List importDirectives = namespace.getImportDirectives(); + for (JetImportDirective importDirective : importDirectives) { + if (importDirective.isAbsoluteInRootNamespace()) { + context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO + continue; + } + if (importDirective.isAllUnder()) { + JetExpression importedReference = importDirective.getImportedReference(); + if (importedReference != null) { + ExpressionTypingServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace()); + JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference); + if (type != null) { + namespaceScope.importScope(type.getMemberScope()); + } + } + } + else { + ClassifierDescriptor classifierDescriptor = null; + NamespaceDescriptor namespaceDescriptor = null; + JetSimpleNameExpression referenceExpression = null; + + JetExpression importedReference = importDirective.getImportedReference(); + if (importedReference instanceof JetDotQualifiedExpression) { + JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference; + JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression()); + JetExpression selectorExpression = reference.getSelectorExpression(); + if (selectorExpression != null) { + referenceExpression = (JetSimpleNameExpression) selectorExpression; + String referencedName = referenceExpression.getReferencedName(); + if (type != null && referencedName != null) { + classifierDescriptor = type.getMemberScope().getClassifier(referencedName); + namespaceDescriptor = type.getMemberScope().getNamespace(referencedName); + } + } + } + else { + assert importedReference instanceof JetSimpleNameExpression; + referenceExpression = (JetSimpleNameExpression) importedReference; + + String referencedName = referenceExpression.getReferencedName(); + if (referencedName != null) { + classifierDescriptor = outerScope.getClassifier(referencedName); + namespaceDescriptor = outerScope.getNamespace(referencedName); + + if (classifierDescriptor == null && namespaceDescriptor == null) { + context.getTrace().report(UNRESOLVED_REFERENCE.on(referenceExpression)); + } + } + } + + String aliasName = importDirective.getAliasName(); + if (aliasName == null) { + aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null; + } + if (classifierDescriptor != null) { + context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor); + + if (aliasName != null) { + namespaceScope.importClassifierAlias(aliasName, classifierDescriptor); + } + } + if (namespaceDescriptor != null) { + if (classifierDescriptor == null) { + context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor); + } + if (aliasName != null) { + namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor); + } + } + } + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 6a694ed7d99..435fed20e44 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -15,7 +15,10 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeConstructor; +import org.jetbrains.jet.lang.types.TypeProjection; +import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lexer.JetTokens; @@ -30,17 +33,19 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*; */ public class TypeHierarchyResolver { private final TopDownAnalysisContext context; + private final ImportsResolver importsResolver; private LinkedList topologicalOrder; public TypeHierarchyResolver(TopDownAnalysisContext context) { this.context = context; + this.importsResolver = new ImportsResolver(context); } public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection declarations) { collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes - processTypeImports(); + importsResolver.processTypeImports(); createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) @@ -75,7 +80,6 @@ public class TypeHierarchyResolver { WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace())); namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH); - context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope); context.getNamespaceScopes().put(namespace, namespaceScope); context.getDeclaringScopes().put(namespace, outerScope); @@ -233,82 +237,6 @@ public class TypeHierarchyResolver { return ClassKind.CLASS; } - private void processTypeImports() { - for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) { - processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace)); - } - } - - private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) { - List importDirectives = namespace.getImportDirectives(); - for (JetImportDirective importDirective : importDirectives) { - if (importDirective.isAbsoluteInRootNamespace()) { - context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO - continue; - } - if (importDirective.isAllUnder()) { - JetExpression importedReference = importDirective.getImportedReference(); - if (importedReference != null) { - ExpressionTypingServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace()); - JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference); - if (type != null) { - namespaceScope.importScope(type.getMemberScope()); - } - } - } - else { - ClassifierDescriptor classifierDescriptor = null; - NamespaceDescriptor namespaceDescriptor = null; - JetSimpleNameExpression referenceExpression = null; - - JetExpression importedReference = importDirective.getImportedReference(); - if (importedReference instanceof JetDotQualifiedExpression) { - JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference; - JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression()); - JetExpression selectorExpression = reference.getSelectorExpression(); - if (selectorExpression != null) { - referenceExpression = (JetSimpleNameExpression) selectorExpression; - String referencedName = referenceExpression.getReferencedName(); - if (type != null && referencedName != null) { - classifierDescriptor = type.getMemberScope().getClassifier(referencedName); - namespaceDescriptor = type.getMemberScope().getNamespace(referencedName); - } - } - } - else { - assert importedReference instanceof JetSimpleNameExpression; - referenceExpression = (JetSimpleNameExpression) importedReference; - - String referencedName = referenceExpression.getReferencedName(); - if (referencedName != null) { - classifierDescriptor = outerScope.getClassifier(referencedName); - namespaceDescriptor = outerScope.getNamespace(referencedName); - } - } - - String aliasName = importDirective.getAliasName(); - if (aliasName == null) { - aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null; - } - if (classifierDescriptor != null) { - context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor); - - if (aliasName != null) { - namespaceScope.importClassifierAlias(aliasName, classifierDescriptor); - } - } - if (namespaceDescriptor != null) { - if (classifierDescriptor == null) { - context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor); - } - if (aliasName != null) { - namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor); - } - } - } - } - } - private void createTypeConstructors() { for (Map.Entry entry : context.getClasses().entrySet()) { JetClass jetClass = entry.getKey(); diff --git a/compiler/testData/diagnostics/tests/regressions/kt762.jet b/compiler/testData/diagnostics/tests/regressions/kt762.jet new file mode 100644 index 00000000000..848d478794e --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/kt762.jet @@ -0,0 +1,4 @@ +//KT-762 Wrong highlighting in imports (No errors reported on unresolved imports) +import aaa // must be an error + +fun main(args : Array) {} \ No newline at end of file From 41111c3bee291e087cbb6e5cf701ee0199c96fe0 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 7 Dec 2011 15:36:07 +0200 Subject: [PATCH 07/20] spectral norm benchmark --- examples/src/benchmarks/SpectralNorm.java | 169 ++++++++++++++++++++++ examples/src/benchmarks/SpectralNorm.kt | 128 ++++++++++++++++ 2 files changed, 297 insertions(+) create mode 100644 examples/src/benchmarks/SpectralNorm.java create mode 100644 examples/src/benchmarks/SpectralNorm.kt diff --git a/examples/src/benchmarks/SpectralNorm.java b/examples/src/benchmarks/SpectralNorm.java new file mode 100644 index 00000000000..c67eb068dd7 --- /dev/null +++ b/examples/src/benchmarks/SpectralNorm.java @@ -0,0 +1,169 @@ +/* +The Computer Language Benchmarks Game +http://shootout.alioth.debian.org/ + +Based on C# entry by Isaac Gouy +contributed by Jarkko Miettinen +Parallel by The Anh Tran +*/ + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.concurrent.CyclicBarrier; + +public class SpectralNorm +{ + private static final NumberFormat formatter = new DecimalFormat ("#.000000000"); + + public static void main (String[] args) + { + int n = 5500; + if (args.length > 0) n = Integer.parseInt (args[0]); + + final long millis = System.currentTimeMillis(); + System.out.println (formatter.format (spectralnormGame (n)) ); + long total = System.currentTimeMillis() - millis; + System.out.println("[SpectralNorm-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]"); + } + + + private static final double spectralnormGame (int n) + { + // create unit vector + double[] u = new double[n]; + double[] v = new double[n]; + double[] tmp = new double[n]; + + for (int i = 0; i < n; i++) + u[i] = 1.0; + + // get available processor, then set up syn object + int nthread = Runtime.getRuntime ().availableProcessors (); + Approximate.barrier = new CyclicBarrier (nthread); + + int chunk = n / nthread; + Approximate[] ap = new Approximate[nthread]; + + for (int i = 0; i < nthread; i++) + { + int r1 = i * chunk; + int r2 = (i < (nthread -1)) ? r1 + chunk : n; + + ap[i] = new Approximate (u, v, tmp, r1, r2); + } + + + double vBv = 0, vv = 0; + for (int i = 0; i < nthread; i++) + { + try + { + ap[i].join (); + + vBv += ap[i].m_vBv; + vv += ap[i].m_vv; + } + catch (Exception e) + { + e.printStackTrace (); + } + } + + return Math.sqrt (vBv/vv); + } + + + private static class Approximate extends Thread + { + private static CyclicBarrier barrier; + + private double[] _u; + private double[] _v; + private double[] _tmp; + + private int range_begin, range_end; + private double m_vBv = 0, m_vv = 0; + + + public Approximate (double[] u, double[] v, double[] tmp, int rbegin, int rend) + { + super (); + + _u = u; + _v = v; + _tmp = tmp; + + range_begin = rbegin; + range_end = rend; + + start (); + } + + public void run () + { + // 20 steps of the power method + for (int i = 0; i < 10; i++) + { + MultiplyAtAv (_u, _tmp, _v); + MultiplyAtAv (_v, _tmp, _u); + } + + for (int i = range_begin; i < range_end; i++) + { + m_vBv += _u[i] * _v[i]; + m_vv += _v[i] * _v[i]; + } + } + + /* return element i,j of infinite matrix A */ + private final static double eval_A (int i, int j) + { + int div = ( ((i+j) * (i+j+1) >>> 1) +i+1 ); + return 1.0 / div; + } + + /* multiply vector v by matrix A, each thread evaluate its range only */ + private final void MultiplyAv (final double[] v, double[] Av) + { + for (int i = range_begin; i < range_end; i++) + { + double sum = 0; + for (int j = 0; j < v.length; j++) + sum += eval_A (i, j) * v[j]; + + Av[i] = sum; + } + } + + /* multiply vector v by matrix A transposed */ + private final void MultiplyAtv (final double[] v, double[] Atv) + { + for (int i = range_begin; i < range_end; i++) + { + double sum = 0; + for (int j = 0; j < v.length; j++) + sum += eval_A (j, i) * v[j]; + + Atv[i] = sum; + } + } + + /* multiply vector v by matrix A and then by matrix A transposed */ + private final void MultiplyAtAv (final double[] v, double[] tmp, double[] AtAv) + { + try + { + MultiplyAv (v, tmp); + // all thread must syn at completion + barrier.await (); + MultiplyAtv (tmp, AtAv); + // all thread must syn at completion + barrier.await (); + } + catch (Exception e) + { + e.printStackTrace (); + } + } + } +} \ No newline at end of file diff --git a/examples/src/benchmarks/SpectralNorm.kt b/examples/src/benchmarks/SpectralNorm.kt new file mode 100644 index 00000000000..930302bba87 --- /dev/null +++ b/examples/src/benchmarks/SpectralNorm.kt @@ -0,0 +1,128 @@ +namespace spectralnorm + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.concurrent.CyclicBarrier; + +val formatter = DecimalFormat ("#.000000000"); + +fun main (args : Array) { + var n = 5500 + if (args.size > 0) + n = Integer.parseInt (args[0]); + + val millis = System.currentTimeMillis() + System.out?.println (formatter.format (spectralnormGame (n)) ) + val total = System.currentTimeMillis() - millis; + System.out?.println("[SpectralNorm-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]"); +} + +fun spectralnormGame(n: Int) : Double { + val u = DoubleArray(n) + val v = DoubleArray(n) + val tmp = DoubleArray(n) + + for(i in u.indices) { + u[i] = 1.0 + } + + val nthread = Runtime.getRuntime ().sure().availableProcessors (); + barrier = CyclicBarrier (nthread); + + val chunk = n / nthread + val ap = Array(nthread,{ + val r1 = it * chunk; + val r2 = if(it < (nthread -1)) r1 + chunk else nthread; + + Approximate (u, v, tmp, r1, r2) + }) + + var vBv = 0.dbl + var vv = 0.dbl; + for (i in 0..nthread-1) { + try { + ap[i].join (); + + vBv += ap[i].m_vBv; + vv += ap[i].m_vv; + } + catch (e: Exception ) + { + e.printStackTrace (); + } + } + + return Math.sqrt (vBv/vv); +} + +fun eval_A (i: Int, j: Int) = 1.0 / ( ((i+j) * (i+j+1) shr 1) +i+1 ) + +var barrier : CyclicBarrier? = null + +class Approximate(val u: DoubleArray, val v: DoubleArray, val _tmp: DoubleArray, val rbegin: Int, val rend: Int) : Thread() { + class object { + } + + var m_vBv = 0.0 + var m_vv = 0.0 + + { + start() + } + + override fun run () { + for(i in 0..10) { + MultiplyAtAv (u, _tmp, v); + MultiplyAtAv (v, _tmp, u); + } + + for(i in rbegin..rend) { + m_vBv += u[i] * v[i]; + m_vv += v[i] * v[i]; + } + } + +/* multiply vector v by matrix A, each thread evaluate its range only */ + fun MultiplyAv (v: DoubleArray, Av: DoubleArray) + { + for (i in rbegin..rend) + { + var sum = 0.0; + for (j in v.indices) + sum += eval_A (i, j) * v[j]; + + Av[i] = sum; + } + } + +/* multiply vector v by matrix A transposed */ + fun MultiplyAtv (v: DoubleArray, Atv: DoubleArray) + { + for (i in rbegin..rend) + { + var sum = 0.dbl + for (j in v.indices) + sum += eval_A (j, i) * v[j]; + + Atv[i] = sum; + } + } + +/* multiply vector v by matrix A and then by matrix A transposed */ + fun MultiplyAtAv (v: DoubleArray, tmp: DoubleArray, AtAv: DoubleArray) + { + try + { + MultiplyAv (v, tmp); + // all thread must syn at completion + barrier?.await (); + MultiplyAtv (tmp, AtAv); + // all thread must syn at completion + barrier?.await (); + } + catch (e: Exception) + { + e.printStackTrace (); + } + } +} \ No newline at end of file From 2270ab3cba26599287471c7ba5dc40cf21dced89 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 7 Dec 2011 17:37:54 +0400 Subject: [PATCH 08/20] KT-750 Type inference failed: Constraint violation --- .../testData/diagnostics/tests/regressions/kt750.jet | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/regressions/kt750.jet diff --git a/compiler/testData/diagnostics/tests/regressions/kt750.jet b/compiler/testData/diagnostics/tests/regressions/kt750.jet new file mode 100644 index 00000000000..9e9760acb17 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/kt750.jet @@ -0,0 +1,9 @@ +// +JDK +//KT-750 Type inference failed: Constraint violation +fun main(args : Array) { + var i : Int? = Integer.valueOf(100) + var s : Int? = Integer.valueOf(100) + + val o = i .sure() + s.sure() + System.out?.println(o) +} From ae03b4531ea5850da849c447d37d59296cc68093 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 7 Dec 2011 19:45:21 +0400 Subject: [PATCH 09/20] Debug info for overload resolution/type inference --- .../jet/lang/resolve/calls/CallResolver.java | 22 ++- .../resolve/calls/ResolutionDebugInfo.java | 115 +++++++++++++ .../ConstraintResolutionListener.java | 19 +++ .../calls/inference/ConstraintSystemImpl.java | 156 ++++++++---------- .../DebugConstraintResolutionListener.java | 75 +++++++++ .../PrintingConstraintResolutionListener.java | 55 ++++++ .../jet/util/slicedmap/SlicedMap.java | 25 +++ .../resolvewindow/ResolveToolwindow.java | 99 +++++++++-- 8 files changed, 460 insertions(+), 106 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index f73557fcdd4..3db5f295442 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -13,16 +13,13 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.calls.inference.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; 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.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.OperatorConventions; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; -import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus; import org.jetbrains.jet.lexer.JetTokens; import java.util.*; @@ -241,6 +238,12 @@ public class CallResolver { @NotNull JetType expectedType, @NotNull final List> prioritizedTasks, // high to low priority @NotNull final JetReferenceExpression reference) { + + ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); + trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, call.getCallElement(), debugInfo); + + debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks); + TracingStrategy tracing = new TracingStrategy() { @Override public void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl resolvedCall) { @@ -371,6 +374,9 @@ public class CallResolver { OverloadResolutionResults results = performResolution(temporaryTrace, scope, expectedType, task, tracing); if (results.isSuccess()) { temporaryTrace.commit(); + + debugInfo.set(ResolutionDebugInfo.RESULT, results.getResult()); + return results.getResult(); } if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) { @@ -381,6 +387,9 @@ public class CallResolver { if (traceForFirstNonemptyCandidateSet != null) { traceForFirstNonemptyCandidateSet.commit(); if (resultsForFirstNonemptyCandidateSet.singleDescriptor()) { + + debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResult()); + return resultsForFirstNonemptyCandidateSet.getResult(); } } @@ -420,7 +429,10 @@ public class CallResolver { if (!candidate.getTypeParameters().isEmpty()) { // Type argument inference - ConstraintSystem constraintSystem = new ConstraintSystemImpl(); + ResolutionDebugInfo.Data debugInfo = trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, task.getCall().getCallElement()); + + ConstraintSystem constraintSystem = new ConstraintSystemImpl(new DebugConstraintResolutionListener(debugInfo)); + for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) { constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java new file mode 100644 index 00000000000..59968bae9a4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java @@ -0,0 +1,115 @@ +package org.jetbrains.jet.lang.resolve.calls; + +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.util.slicedmap.*; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * @author abreslav + */ +public class ResolutionDebugInfo { + public static final WritableSlice>> TASKS = Slices.createSimpleSlice(); + public static final WritableSlice> RESULT = Slices.createSimpleSlice(); + public static final WritableSlice ERRORS = Slices.createSimpleSlice(); + public static final WritableSlice LOG = Slices.createSimpleSlice(); + public static final WritableSlice> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice(); + public static final WritableSlice> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice(); + public static final WritableSlice SOLUTION = Slices.createSimpleSlice(); + public static final WritableSlice> UNKNOWNS = Slices.createSimpleSlice(); + + static { + BasicWritableSlice.initSliceDebugNames(ResolutionDebugInfo.class); + } + + public static boolean RESOLUTION_DEBUG_INFO_ENABLED = false; + + public static boolean isResolutionDebugEnabled() { + Application application = ApplicationManager.getApplication(); + return (RESOLUTION_DEBUG_INFO_ENABLED || application.isInternal()) && !application.isUnitTestMode(); + } + + public static final Data NO_DEBUG_INFO = new AbstractData() { + + @Override + public String toString() { + return "NO_DEBUG_INFO"; + } + + @Override + public V getByKey(ReadOnlySlice slice, K key) { + return SlicedMap.DO_NOTHING.get(slice, key); + } + + @Override + public void putByKey(WritableSlice slice, K key, V value) { + } + }; + public static final WritableSlice RESOLUTION_DEBUG_INFO = new BasicWritableSlice(Slices.ONLY_REWRITE_TO_EQUAL) { + @Override + public boolean check(PsiElement key, Data value) { + return isResolutionDebugEnabled(); + } + + @Override + public Data computeValue(SlicedMap map, PsiElement key, Data value, boolean valueNotFound) { + if (valueNotFound) return NO_DEBUG_INFO; + return super.computeValue(map, key, value, valueNotFound); + } + }; + + public static Data create() { + return isResolutionDebugEnabled() ? new DataImpl() : NO_DEBUG_INFO; + } + + public enum One { KEY } + + public interface Data { + V getByKey(ReadOnlySlice slice, K key); + void putByKey(WritableSlice slice, K key, V value); + + void set(WritableSlice slice, V value); + V get(ReadOnlySlice slice); + } + + private static abstract class AbstractData implements Data { + @Override + public void set(WritableSlice slice, V value) { + putByKey(slice, One.KEY, value); + } + + @Override + public V get(ReadOnlySlice slice) { + return getByKey(slice, One.KEY); + } + } + + private static class DataImpl extends AbstractData { + private final MutableSlicedMap map = SlicedMapImpl.create(); + + @Override + public V getByKey(ReadOnlySlice slice, K key) { + return map.get(slice, key); + } + + @Override + public void putByKey(WritableSlice slice, K key, V value) { + map.put(slice, key, value); + } + } + + public static void println(Object message) { + if (isResolutionDebugEnabled()) { + System.out.println(message); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java new file mode 100644 index 00000000000..783f6591e32 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java @@ -0,0 +1,19 @@ +package org.jetbrains.jet.lang.resolve.calls.inference; + +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.types.JetType; + +import java.util.Set; + +/** + * @author abreslav + */ +public interface ConstraintResolutionListener { + + void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue); + void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue); + void done(ConstraintSystemSolution solution, Set typeParameterDescriptors); + + void log(Object message); + void error(Object message); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index fd274762a09..e6f8263432f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -44,7 +44,6 @@ public class ConstraintSystemImpl implements ConstraintSystem { }); } - private static class LoopInTypeVariableConstraintsException extends RuntimeException { public LoopInTypeVariableConstraintsException() {} } @@ -80,6 +79,8 @@ public class ConstraintSystemImpl implements ConstraintSystem { public abstract boolean equate(TypeValue other); } +//========================================================================================================================================================== + private class UnknownType extends TypeValue { private final TypeParameterDescriptor typeParameterDescriptor; @@ -142,7 +143,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { } } - println("minimal solution from lowerbounds for " + this + " is " + commonSupertype); + listener.log("minimal solution from lowerbounds for " + this + " is " + commonSupertype); value = new KnownType(commonSupertype); } else { @@ -238,16 +239,18 @@ public class ConstraintSystemImpl implements ConstraintSystem { private static final class TypeConstraintBuilderAdapter implements TypingConstraints { private final TypingConstraints delegate; + private final ConstraintResolutionListener listener; - private TypeConstraintBuilderAdapter(TypingConstraints delegate) { + private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) { this.delegate = delegate; + this.listener = listener; } @Override public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) { boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure); if (!result) { - println("-- Failed to equate " + a + " and " + b); + listener.error("-- Failed to equate " + a + " and " + b); } return result; } @@ -256,7 +259,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { boolean result = delegate.assertEqualTypeConstructors(a, b); if (!result) { - println("-- Type constructors are not equal: " + a + " and " + b); + listener.error("-- Type constructors are not equal: " + a + " and " + b); } return result; } @@ -265,7 +268,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) { boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure); if (!result) { - println("-- " + subtype + " can't be a subtype of " + supertype); + listener.error("-- " + subtype + " can't be a subtype of " + supertype); } return result; } @@ -274,60 +277,67 @@ public class ConstraintSystemImpl implements ConstraintSystem { public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { boolean result = delegate.noCorrespondingSupertype(subtype, supertype); if (!result) { - println("-- " + subtype + " has no supertype corresponding to " + supertype); + listener.error("-- " + subtype + " has no supertype corresponding to " + supertype); } return result; } } - - private final TypeCheckingProcedure constraintExpander = new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() { - @Override - public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) { - TypeValue aValue = getTypeValueFor(a); - TypeValue bValue = getTypeValueFor(b); - return aValue.equate(bValue); - } + private final TypeCheckingProcedure constraintExpander; + private final ConstraintResolutionListener listener; - @Override - public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { - return a.equals(b) - || unknownTypes.containsKey(a.getDeclarationDescriptor()) - || unknownTypes.containsKey(b.getDeclarationDescriptor()); - } + public ConstraintSystemImpl(ConstraintResolutionListener listener) { + this.listener = listener; + this.constraintExpander = createConstraintExpander(); + } - @Override - public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) { - TypeValue subtypeValue = getTypeValueFor(subtype); - TypeValue supertypeValue = getTypeValueFor(supertype); + private TypeCheckingProcedure createConstraintExpander() { + return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() { + @Override + public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) { + TypeValue aValue = getTypeValueFor(a); + TypeValue bValue = getTypeValueFor(b); - if (someUnknown(subtypeValue, supertypeValue)) { - addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue); + return aValue.equate(bValue); } - return true; - } - @Override - public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { - // If some of the types is an unknown, the constraint must be generated, and we should carry on - // otherwise there can be no solution, and we should fail - TypeValue subTypeValue = getTypeValueFor(subtype); - TypeValue superTypeValue = getTypeValueFor(supertype); - boolean someUnknown = someUnknown(subTypeValue, superTypeValue); - if (someUnknown) { - addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue); + @Override + public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { + return a.equals(b) + || unknownTypes.containsKey(a.getDeclarationDescriptor()) + || unknownTypes.containsKey(b.getDeclarationDescriptor()); } - return someUnknown; - } - private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) { - return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType; - } + @Override + public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) { + TypeValue subtypeValue = getTypeValueFor(subtype); + TypeValue supertypeValue = getTypeValueFor(supertype); - })) - ; + if (someUnknown(subtypeValue, supertypeValue)) { + addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue); + } + return true; + } - public ConstraintSystemImpl() {} + @Override + public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { + // If some of the types is an unknown, the constraint must be generated, and we should carry on + // otherwise there can be no solution, and we should fail + TypeValue subTypeValue = getTypeValueFor(subtype); + TypeValue superTypeValue = getTypeValueFor(supertype); + boolean someUnknown = someUnknown(subTypeValue, superTypeValue); + if (someUnknown) { + addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue); + } + return someUnknown; + } + + private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) { + return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType; + } + + }, listener)); + } @NotNull private TypeValue getTypeValueFor(@NotNull JetType type) { @@ -368,7 +378,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { } private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) { - System.err.println("!!!mergeUnknowns() is not implemented!!!"); + listener.error("!!!mergeUnknowns() is not implemented!!!"); } @Override @@ -379,7 +389,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { } private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) { - println(typeValueForLower + " :< " + typeValueForUpper); + listener.log("Constraint added: " + typeValueForLower + " :< " + typeValueForUpper); if (typeValueForLower != typeValueForUpper) { typeValueForLower.addUpperBound(typeValueForUpper); typeValueForUpper.addLowerBound(typeValueForLower); @@ -424,13 +434,11 @@ public class ConstraintSystemImpl implements ConstraintSystem { } for (UnknownType unknownType : unknownTypes.values()) { - println("Constraints for " + unknownType.getTypeParameterDescriptor()); - printTypeValue(unknownType); + listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType); } for (KnownType knownType : knownTypes.values()) { - println("Constraints for " + knownType.getType()); - printTypeValue(knownType); + listener.constraintsForKnownType(knownType.getType(), knownType); } // Find inconsistencies @@ -447,22 +455,11 @@ public class ConstraintSystemImpl implements ConstraintSystem { // we have set some of them from equality constraints with known types // and thus the bounds may be violated if some of the constraints conflict - println("===================================="); - println(""); - println(""); + listener.done(solution, unknownTypes.keySet()); return solution; } - private void printTypeValue(TypeValue typeValue) { - for (TypeValue bound : typeValue.getUpperBounds()) { - println(" :< " + bound); - } - for (TypeValue bound : typeValue.getLowerBounds()) { - println(" :> " + bound); - } - } - private void check(TypeValue typeValue, Solution solution) { try { KnownType resultingValue = typeValue.getValue(); @@ -471,33 +468,20 @@ public class ConstraintSystemImpl implements ConstraintSystem { JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT); if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType); - println("Constraint violation: " + type + " :< " + boundingType); + listener.error("Constraint violation: " + type + " :< " + boundingType); } } for (TypeValue lowerBound : typeValue.getLowerBounds()) { JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT); if (!typeChecker.isSubtypeOf(boundingType, type)) { solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type); - println("Constraint violation: " + boundingType + " :< " + type); + listener.error("Constraint violation: " + boundingType + " :< " + type); } } } catch (LoopInTypeVariableConstraintsException e) { - println("-------------------------------------------------------------------"); - for (Map.Entry entry : unknownTypes.entrySet()) { - println("Unknown: " + entry.getKey()); - UnknownType unknownType = entry.getValue(); - println("Lower bounds: "); - for (TypeValue lowerBound : unknownType.getLowerBounds()) { - println(" " + lowerBound); - } - println("Upper bounds: "); - for (TypeValue lowerBound : unknownType.getUpperBounds()) { - println(" " + lowerBound); - } - } + listener.error("Loop detected"); solution.registerError("[TODO] Loop in constraints"); -// e.printStackTrace(); } } @@ -544,9 +528,14 @@ public class ConstraintSystemImpl implements ConstraintSystem { DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); if (declarationDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; + if (!unknownTypes.containsKey(descriptor)) return null; - println(descriptor + " |-> " + getValue(descriptor)); - return new TypeProjection(getValue(descriptor)); + + TypeProjection typeProjection = new TypeProjection(getValue(descriptor)); + + listener.log(descriptor + " |-> " + typeProjection); + + return typeProjection; } return null; } @@ -588,7 +577,4 @@ public class ConstraintSystemImpl implements ConstraintSystem { } - private static void println(String message) { -// System.out.println(message); - } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java new file mode 100644 index 00000000000..b6e5731f7cf --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java @@ -0,0 +1,75 @@ +package org.jetbrains.jet.lang.resolve.calls.inference; + +import com.google.common.collect.Maps; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo; +import org.jetbrains.jet.lang.types.JetType; + +import java.util.Map; +import java.util.Set; + +import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*; + +/** + * @author abreslav + */ +public class DebugConstraintResolutionListener implements ConstraintResolutionListener { + + private final ResolutionDebugInfo.Data debugInfo; + + public DebugConstraintResolutionListener(@NotNull ResolutionDebugInfo.Data debugInfo) { + this.debugInfo = debugInfo; + } + + @Override + public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) { + if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; + Map map = debugInfo.get(BOUNDS_FOR_UNKNOWNS); + if (map == null) { + map = Maps.newLinkedHashMap(); + debugInfo.set(BOUNDS_FOR_UNKNOWNS, map); + } + map.put(typeParameterDescriptor, typeValue); + } + + @Override + public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) { + if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; + Map map = debugInfo.get(BOUNDS_FOR_KNOWNS); + if (map == null) { + map = Maps.newLinkedHashMap(); + debugInfo.set(BOUNDS_FOR_KNOWNS, map); + } + map.put(type, typeValue); + } + + @Override + public void done(ConstraintSystemSolution solution, Set typeParameterDescriptors) { + if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; + debugInfo.set(SOLUTION, solution); + debugInfo.set(UNKNOWNS, typeParameterDescriptors); + } + + @Override + public void log(Object message) { + if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; + StringBuilder stringBuilder = debugInfo.get(LOG); + if (stringBuilder == null) { + stringBuilder = new StringBuilder(); + debugInfo.set(LOG, stringBuilder); + } + stringBuilder.append(message).append("\n"); + } + + @Override + public void error(Object message) { + if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; + StringBuilder stringBuilder = debugInfo.get(ERRORS); + if (stringBuilder == null) { + stringBuilder = new StringBuilder(); + debugInfo.set(ERRORS, stringBuilder); + } + stringBuilder.append(message).append("\n"); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java new file mode 100644 index 00000000000..3fe1a169eeb --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java @@ -0,0 +1,55 @@ +package org.jetbrains.jet.lang.resolve.calls.inference; + +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo; +import org.jetbrains.jet.lang.types.JetType; + +import java.util.Set; + +/** + * @author abreslav + */ +public class PrintingConstraintResolutionListener implements ConstraintResolutionListener { + + @Override + public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) { + println("Constraints for " + typeParameterDescriptor); + printTypeValue(typeValue); + } + + @Override + public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) { + println("Constraints for " + type); + printTypeValue(typeValue); + } + + @Override + public void done(ConstraintSystemSolution solution, Set typeParameterDescriptors) { + println("=================================================="); + println(""); + println(""); + } + + @Override + public void log(Object message) { + println(message); + } + + @Override + public void error(Object message) { + println(message); + } + + private void printTypeValue(ConstraintSystemImpl.TypeValue typeValue) { + for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) { + println(" :< " + bound); + } + for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) { + println(" :> " + bound); + } + } + + private static void println(Object message) { + ResolutionDebugInfo.println(message); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMap.java b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMap.java index 79e26176135..f06598d2cb3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMap.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMap.java @@ -1,12 +1,37 @@ package org.jetbrains.jet.util.slicedmap; import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; import java.util.Map; /** * @author abreslav */ public interface SlicedMap extends Iterable, ?>> { + + SlicedMap DO_NOTHING = new SlicedMap() { + @Override + public V get(ReadOnlySlice slice, K key) { + return slice.computeValue(this, key, null, true); + } + + @Override + public boolean containsKey(ReadOnlySlice slice, K key) { + return false; + } + + @Override + public Collection getKeys(WritableSlice slice) { + return Collections.emptySet(); + } + + @Override + public Iterator, ?>> iterator() { + return Collections., ?>>emptySet().iterator(); + } + }; + V get(ReadOnlySlice slice, K key); boolean containsKey(ReadOnlySlice slice, K key); diff --git a/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java b/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java index 4e35628ae2b..94a47c390c7 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java @@ -21,27 +21,31 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.content.ContentFactory; import com.intellij.util.Alarm; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; 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.JetReferenceExpression; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow; +import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; +import org.jetbrains.jet.util.slicedmap.WritableSlice; import javax.swing.*; import java.awt.*; import java.util.Map; -import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE; -import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; -import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; +import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*; /* * @author abreslav @@ -121,19 +125,20 @@ public class ResolveToolwindow extends JPanel { PsiElement currentElement = elementAtOffset; boolean callFound = false; - while (currentElement != null && !(currentElement instanceof PsiFile)) { - if (currentElement instanceof JetElement) { - JetElement atOffset = (JetElement) currentElement; - ResolvedCall resolvedCall = bindingContext.get(RESOLVED_CALL, (JetElement) atOffset); - if (resolvedCall != null) { - setText(renderCall(resolvedCall) + "\n===\n" + currentElement + ": " + currentElement.getText()); - callFound = true; - break; - } - } - currentElement = currentElement.getParent(); + PsiElement elementWithDebugInfo = findData(bindingContext, currentElement, RESOLUTION_DEBUG_INFO); + if (elementWithDebugInfo != null) { + callFound = true; + setText(renderDebugInfo(elementWithDebugInfo, bindingContext.get(RESOLUTION_DEBUG_INFO, elementWithDebugInfo), null)); } + else { + PsiElement elementWithResolvedCall = findData(bindingContext, currentElement, (WritableSlice) RESOLVED_CALL); + if (elementWithResolvedCall instanceof JetElement) { + callFound = true; + setText(renderDebugInfo(elementWithResolvedCall, null, bindingContext.get(RESOLVED_CALL, (JetElement) elementWithResolvedCall))); + } + } + if (!callFound) { JetExpression parentExpression = (elementAtOffset instanceof JetExpression) ? (JetExpression) elementAtOffset @@ -153,8 +158,70 @@ public class ResolveToolwindow extends JPanel { } } - private String renderCall(ResolvedCall resolvedCall) { - StringBuilder builder = new StringBuilder(); + @Nullable + private PsiElement findData(BindingContext bindingContext, PsiElement currentElement, ReadOnlySlice slice) { + while (currentElement != null && !(currentElement instanceof PsiFile)) { + if (currentElement instanceof JetElement) { + JetElement atOffset = (JetElement) currentElement; + D data = bindingContext.get(slice, atOffset); + if (data != null && data != NO_DEBUG_INFO) { + return currentElement; + } + + } + currentElement = currentElement.getParent(); + } + return null; + } + + private String renderDebugInfo(PsiElement currentElement, @Nullable ResolutionDebugInfo.Data debugInfo, @Nullable ResolvedCall call) { + final String bar = "\n\n===\n\n"; + + StringBuilder result = new StringBuilder(); + + if (debugInfo != null) { + StringBuilder errors = debugInfo.get(ERRORS); + if (errors != null) { + result.append("Errors: \n").append(errors).append(bar); + } + + StringBuilder log = debugInfo.get(LOG); + if (log != null) { + result.append("Log: \n").append(log).append(bar); + } + + Map knowns = debugInfo.get(BOUNDS_FOR_KNOWNS); + renderMap(knowns, result); + Map unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS); + renderMap(unknowns, result); + + result.append(bar); + + call = debugInfo.get(RESULT); + } + + renderCall(result, call); + result.append(currentElement + ": " + currentElement.getText()); + return result.toString(); + } + + private void renderMap(Map map, StringBuilder builder) { + if (map == null) return; + + for (Map.Entry entry : map.entrySet()) { + K key = entry.getKey(); + ConstraintSystemImpl.TypeValue typeValue = entry.getValue(); + builder.append("Bounds for ").append(key).append("\n"); + for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) { + builder.append(" >: ").append(bound).append("\n"); + } + for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) { + builder.append(" <: ").append(bound).append("\n"); + } + } + } + + private String renderCall(StringBuilder builder, ResolvedCall resolvedCall) { CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument(); From 242c59ffa6cc399e13d9009b54080c88d8e38f8d Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 7 Dec 2011 19:55:44 +0400 Subject: [PATCH 10/20] Test fixed after adding debug info --- compiler/tests/org/jetbrains/jet/JetTestUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index 3187caacb4e..ed43b181be0 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; +import org.jetbrains.jet.util.slicedmap.SlicedMap; import org.jetbrains.jet.util.slicedmap.WritableSlice; import java.util.Collection; @@ -55,7 +56,7 @@ public class JetTestUtils { @Override public V get(ReadOnlySlice slice, K key) { if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE; - return null; + return SlicedMap.DO_NOTHING.get(slice, key); } @NotNull From 4cd02c983d352bdbbce11a5fb8382e6023cf41b9 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 7 Dec 2011 20:32:58 +0400 Subject: [PATCH 11/20] CompileJavaAgainstKotlinTest Test is: 1. find pairs of kotlin/java files in compiler/testData/compileJavaAgainstKotlin and for each pair 2. compile kotlin file 3. compile java file with kotlin .class in classpath 4. check everything is OK --- .../jet/codegen/FunctionCodegen.java | 7 +- .../compileJavaAgainstKotlin/Hello.java | 6 + .../compileJavaAgainstKotlin/Hello.kt | 1 + .../jet/CompileJavaAgainstKotlinTest.java | 153 ++++++++++++++++++ 4 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/compileJavaAgainstKotlin/Hello.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/Hello.kt create mode 100644 compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index e730798fbee..248fc165a52 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -7,12 +7,15 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.Method; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; import java.util.List; import java.util.Set; @@ -50,7 +53,7 @@ public class FunctionCodegen { final JetExpression bodyExpression = f.getBodyExpression(); generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f); } - + private void generatedMethod(JetExpression bodyExpressions, Method jvmSignature, CodegenContext.MethodContext context, @@ -73,7 +76,7 @@ public class FunctionCodegen { boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); if (isAbstract) flags |= ACC_ABSTRACT; - + final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); if(v.generateCode()) { int start = 0; diff --git a/compiler/testData/compileJavaAgainstKotlin/Hello.java b/compiler/testData/compileJavaAgainstKotlin/Hello.java new file mode 100644 index 00000000000..4b1fd44184c --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/Hello.java @@ -0,0 +1,6 @@ + +class Hello { + public static void xx() { + int x = namespace.f(); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/Hello.kt b/compiler/testData/compileJavaAgainstKotlin/Hello.kt new file mode 100644 index 00000000000..294b46ba1d1 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/Hello.kt @@ -0,0 +1 @@ +fun f() = 1 diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java new file mode 100644 index 00000000000..8b0cc8d0ff4 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java @@ -0,0 +1,153 @@ +package org.jetbrains.jet; + +import com.intellij.lang.LanguageASTFactory; +import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.impl.PsiFileFactoryImpl; +import com.intellij.psi.impl.source.tree.JavaASTFactory; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.testFramework.UsefulTestCase; +import junit.framework.Test; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.ClassFileFactory; +import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.compiler.CompileEnvironment; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +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.plugin.JetLanguage; +import org.junit.Assert; + +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +/** + * @author Stepan Koltsov + */ +public class CompileJavaAgainstKotlinTest extends UsefulTestCase { + + private final File ktFile; + private final File javaFile; + private JetCoreEnvironment jetCoreEnvironment; + private File tmpdir; + + public CompileJavaAgainstKotlinTest(File ktFile) { + this.ktFile = ktFile; + Assert.assertTrue(ktFile.getName().endsWith(".kt")); + this.javaFile = new File(ktFile.getPath().replaceFirst("\\.kt", ".java")); + } + + private void createMockCoreEnvironment() { + jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); + + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + jetCoreEnvironment.addToClasspath(rtJar); + jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + } + + private void mkdirs(File file) throws IOException { + if (file.isDirectory()) { + return; + } + if (!file.mkdirs()) { + throw new IOException(); + } + } + + private void rmrf(File file) { + if (file != null) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + rmrf(child); + } + } + file.delete(); + } + } + + @Override + public String getName() { + return ktFile.getName(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); + rmrf(tmpdir); + mkdirs(tmpdir); + } + + @Override + public void tearDown() throws Exception { + Disposer.dispose(myTestRootDisposable); + } + + + @Override + protected void runTest() throws Throwable { + createMockCoreEnvironment(); + + LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); + + + String text = FileUtil.loadFile(ktFile); + + LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); + virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); + JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); + + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactory.BINARIES); + AnalyzingUtils.checkForSyntacticErrors(psiFile); + state.compile(psiFile); + + ClassFileFactory classFileFactory = state.getFactory(); + + CompileEnvironment.writeToOutputDirectory(classFileFactory, tmpdir.getPath()); + + Disposer.dispose(myTestRootDisposable); + + JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); + + StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, Locale.ENGLISH, Charset.forName("utf-8")); + try { + Iterable javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(Collections.singleton(javaFile)); + List options = Arrays.asList( + "-classpath", tmpdir.getPath(), + "-d", tmpdir.getPath() + ); + JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, javaFileObjectsFromFiles); + + Assert.assertTrue(task.call()); + } finally { + fileManager.close(); + } + } + + public static Test suite() { + return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/compileJavaAgainstKotlin", true, new JetTestCaseBuilder.NamedTestFactory() { + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { + return new CompileJavaAgainstKotlinTest(file); + } + }); + + } + +} From 8db2617701dc029e87a9e175b5e4f1b1f7c6ab69 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 7 Dec 2011 21:01:51 +0400 Subject: [PATCH 12/20] refactor tests --- .../jet/CompileJavaAgainstKotlinTest.java | 44 ++-------------- .../org/jetbrains/jet/JetLiteFixture.java | 5 +- .../tests/org/jetbrains/jet/JetTestUtils.java | 39 ++++++++++++++ .../org/jetbrains/jet/ReadClassDataTest.java | 52 +++---------------- 4 files changed, 50 insertions(+), 90 deletions(-) diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java index 8b0cc8d0ff4..786e61dfe38 100644 --- a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java @@ -16,10 +16,8 @@ import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.compiler.CompileEnvironment; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; 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.plugin.JetLanguage; import org.junit.Assert; @@ -28,7 +26,6 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.File; -import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; @@ -51,35 +48,6 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { this.javaFile = new File(ktFile.getPath().replaceFirst("\\.kt", ".java")); } - private void createMockCoreEnvironment() { - jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); - - final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); - jetCoreEnvironment.addToClasspath(rtJar); - jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); - } - - private void mkdirs(File file) throws IOException { - if (file.isDirectory()) { - return; - } - if (!file.mkdirs()) { - throw new IOException(); - } - } - - private void rmrf(File file) { - if (file != null) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - rmrf(child); - } - } - file.delete(); - } - } - @Override public String getName() { return ktFile.getName(); @@ -89,26 +57,20 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { protected void setUp() throws Exception { super.setUp(); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); - rmrf(tmpdir); - mkdirs(tmpdir); - } - - @Override - public void tearDown() throws Exception { - Disposer.dispose(myTestRootDisposable); + JetTestUtils.recreateDirectory(tmpdir); } @Override protected void runTest() throws Throwable { - createMockCoreEnvironment(); + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); String text = FileUtil.loadFile(ktFile); - LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); + LightVirtualFile virtualFile = new LightVirtualFile(ktFile.getName(), JetLanguage.INSTANCE, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); diff --git a/compiler/tests/org/jetbrains/jet/JetLiteFixture.java b/compiler/tests/org/jetbrains/jet/JetLiteFixture.java index 987ee56ad2c..9ff4e21f148 100644 --- a/compiler/tests/org/jetbrains/jet/JetLiteFixture.java +++ b/compiler/tests/org/jetbrains/jet/JetLiteFixture.java @@ -53,10 +53,7 @@ public abstract class JetLiteFixture extends UsefulTestCase { } protected void createEnvironmentWithMockJdk() { - myEnvironment = new JetCoreEnvironment(getTestRootDisposable()); - final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); - myEnvironment.addToClasspath(rtJar); - myEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + myEnvironment = JetTestUtils.createEnvironmentWithMockJdk(getTestRootDisposable()); } protected void createEnvironmentWithFullJdk() { diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index ed43b181be0..fea36452872 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -1,5 +1,6 @@ package org.jetbrains.jet; +import com.intellij.openapi.Disposable; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -13,6 +14,8 @@ import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.SlicedMap; import org.jetbrains.jet.util.slicedmap.WritableSlice; +import java.io.File; +import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -128,4 +131,40 @@ public class JetTestUtils { public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { return AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, flowDataTraceFactory); } + + + public static JetCoreEnvironment createEnvironmentWithMockJdk(Disposable disposable) { + JetCoreEnvironment environment = new JetCoreEnvironment(disposable); + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + environment.addToClasspath(rtJar); + environment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + return environment; + } + + + public static void mkdirs(File file) throws IOException { + if (file.isDirectory()) { + return; + } + if (!file.mkdirs()) { + throw new IOException(); + } + } + + public static void rmrf(File file) { + if (file != null) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + rmrf(child); + } + } + file.delete(); + } + } + + public static void recreateDirectory(File dir) throws IOException { + rmrf(dir); + mkdirs(dir); + } } diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java index e97ad3202cd..45037faf1d9 100644 --- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -1,6 +1,5 @@ package org.jetbrains.jet; -import com.intellij.lang.ASTFactory; import com.intellij.lang.LanguageASTFactory; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.Disposable; @@ -35,9 +34,7 @@ import org.jetbrains.jet.plugin.JetLanguage; import org.junit.Assert; import java.io.File; -import java.io.IOException; import java.lang.reflect.Method; -import java.util.Arrays; import java.util.Set; /** @@ -65,54 +62,20 @@ public class ReadClassDataTest extends UsefulTestCase { protected void setUp() throws Exception { super.setUp(); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); - rmrf(tmpdir); - mkdirs(tmpdir); + JetTestUtils.recreateDirectory(tmpdir); } - @Override - public void tearDown() throws Exception { - Disposer.dispose(myTestRootDisposable); - } - - private void mkdirs(File file) throws IOException { - if (file.isDirectory()) { - return; - } - if (!file.mkdirs()) { - throw new IOException(); - } - } - - private void rmrf(File file) { - if (file != null) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - rmrf(child); - } - } - file.delete(); - } - } - - private void createMockCoreEnvironment() { - jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); - - final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); - jetCoreEnvironment.addToClasspath(rtJar); - jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); - } @Override public void runTest() throws Exception { - createMockCoreEnvironment(); + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); String text = FileUtil.loadFile(testFile); - LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); + LightVirtualFile virtualFile = new LightVirtualFile(testFile.getName(), JetLanguage.INSTANCE, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); @@ -129,11 +92,10 @@ public class ReadClassDataTest extends UsefulTestCase { Assert.assertEquals("test", namespaceFromSource.getName()); Disposer.dispose(myTestRootDisposable); - - - - createMockCoreEnvironment(); - + + + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + jetCoreEnvironment.addToClasspath(tmpdir); JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject()); From a16874be6f68b168a4d3ecf3014bbcacafe40768 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 7 Dec 2011 22:06:35 +0400 Subject: [PATCH 13/20] Revert "refactor tests". I've broken tests again. This reverts commit 8db2617701dc029e87a9e175b5e4f1b1f7c6ab69. --- .../jet/CompileJavaAgainstKotlinTest.java | 44 ++++++++++++++-- .../org/jetbrains/jet/JetLiteFixture.java | 5 +- .../tests/org/jetbrains/jet/JetTestUtils.java | 39 -------------- .../org/jetbrains/jet/ReadClassDataTest.java | 52 ++++++++++++++++--- 4 files changed, 90 insertions(+), 50 deletions(-) diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java index 786e61dfe38..8b0cc8d0ff4 100644 --- a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java @@ -16,8 +16,10 @@ import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.compiler.CompileEnvironment; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; 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.plugin.JetLanguage; import org.junit.Assert; @@ -26,6 +28,7 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.File; +import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; @@ -48,6 +51,35 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { this.javaFile = new File(ktFile.getPath().replaceFirst("\\.kt", ".java")); } + private void createMockCoreEnvironment() { + jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); + + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + jetCoreEnvironment.addToClasspath(rtJar); + jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + } + + private void mkdirs(File file) throws IOException { + if (file.isDirectory()) { + return; + } + if (!file.mkdirs()) { + throw new IOException(); + } + } + + private void rmrf(File file) { + if (file != null) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + rmrf(child); + } + } + file.delete(); + } + } + @Override public String getName() { return ktFile.getName(); @@ -57,20 +89,26 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { protected void setUp() throws Exception { super.setUp(); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); - JetTestUtils.recreateDirectory(tmpdir); + rmrf(tmpdir); + mkdirs(tmpdir); + } + + @Override + public void tearDown() throws Exception { + Disposer.dispose(myTestRootDisposable); } @Override protected void runTest() throws Throwable { - jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + createMockCoreEnvironment(); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); String text = FileUtil.loadFile(ktFile); - LightVirtualFile virtualFile = new LightVirtualFile(ktFile.getName(), JetLanguage.INSTANCE, text); + LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); diff --git a/compiler/tests/org/jetbrains/jet/JetLiteFixture.java b/compiler/tests/org/jetbrains/jet/JetLiteFixture.java index 9ff4e21f148..987ee56ad2c 100644 --- a/compiler/tests/org/jetbrains/jet/JetLiteFixture.java +++ b/compiler/tests/org/jetbrains/jet/JetLiteFixture.java @@ -53,7 +53,10 @@ public abstract class JetLiteFixture extends UsefulTestCase { } protected void createEnvironmentWithMockJdk() { - myEnvironment = JetTestUtils.createEnvironmentWithMockJdk(getTestRootDisposable()); + myEnvironment = new JetCoreEnvironment(getTestRootDisposable()); + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + myEnvironment.addToClasspath(rtJar); + myEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); } protected void createEnvironmentWithFullJdk() { diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index fea36452872..ed43b181be0 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -1,6 +1,5 @@ package org.jetbrains.jet; -import com.intellij.openapi.Disposable; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -14,8 +13,6 @@ import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.SlicedMap; import org.jetbrains.jet.util.slicedmap.WritableSlice; -import java.io.File; -import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -131,40 +128,4 @@ public class JetTestUtils { public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { return AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, flowDataTraceFactory); } - - - public static JetCoreEnvironment createEnvironmentWithMockJdk(Disposable disposable) { - JetCoreEnvironment environment = new JetCoreEnvironment(disposable); - final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); - environment.addToClasspath(rtJar); - environment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); - return environment; - } - - - public static void mkdirs(File file) throws IOException { - if (file.isDirectory()) { - return; - } - if (!file.mkdirs()) { - throw new IOException(); - } - } - - public static void rmrf(File file) { - if (file != null) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - rmrf(child); - } - } - file.delete(); - } - } - - public static void recreateDirectory(File dir) throws IOException { - rmrf(dir); - mkdirs(dir); - } } diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java index 45037faf1d9..e97ad3202cd 100644 --- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -1,5 +1,6 @@ package org.jetbrains.jet; +import com.intellij.lang.ASTFactory; import com.intellij.lang.LanguageASTFactory; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.Disposable; @@ -34,7 +35,9 @@ import org.jetbrains.jet.plugin.JetLanguage; import org.junit.Assert; import java.io.File; +import java.io.IOException; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Set; /** @@ -62,20 +65,54 @@ public class ReadClassDataTest extends UsefulTestCase { protected void setUp() throws Exception { super.setUp(); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); - JetTestUtils.recreateDirectory(tmpdir); + rmrf(tmpdir); + mkdirs(tmpdir); } + @Override + public void tearDown() throws Exception { + Disposer.dispose(myTestRootDisposable); + } + + private void mkdirs(File file) throws IOException { + if (file.isDirectory()) { + return; + } + if (!file.mkdirs()) { + throw new IOException(); + } + } + + private void rmrf(File file) { + if (file != null) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + rmrf(child); + } + } + file.delete(); + } + } + + private void createMockCoreEnvironment() { + jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); + + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + jetCoreEnvironment.addToClasspath(rtJar); + jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + } @Override public void runTest() throws Exception { - jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + createMockCoreEnvironment(); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); String text = FileUtil.loadFile(testFile); - LightVirtualFile virtualFile = new LightVirtualFile(testFile.getName(), JetLanguage.INSTANCE, text); + LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); @@ -92,10 +129,11 @@ public class ReadClassDataTest extends UsefulTestCase { Assert.assertEquals("test", namespaceFromSource.getName()); Disposer.dispose(myTestRootDisposable); - - - jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); - + + + + createMockCoreEnvironment(); + jetCoreEnvironment.addToClasspath(tmpdir); JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject()); From b2917154e01c07eb6b0d31fbfeb2bddb2e13f748 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 7 Dec 2011 22:27:38 +0400 Subject: [PATCH 14/20] extract file utils --- .../jet/CompileJavaAgainstKotlinTest.java | 24 +------------- .../tests/org/jetbrains/jet/JetTestUtils.java | 31 +++++++++++++++++++ .../org/jetbrains/jet/ReadClassDataTest.java | 24 +------------- 3 files changed, 33 insertions(+), 46 deletions(-) diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java index 8b0cc8d0ff4..32fe6c20c93 100644 --- a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java @@ -59,27 +59,6 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); } - private void mkdirs(File file) throws IOException { - if (file.isDirectory()) { - return; - } - if (!file.mkdirs()) { - throw new IOException(); - } - } - - private void rmrf(File file) { - if (file != null) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - rmrf(child); - } - } - file.delete(); - } - } - @Override public String getName() { return ktFile.getName(); @@ -89,8 +68,7 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { protected void setUp() throws Exception { super.setUp(); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); - rmrf(tmpdir); - mkdirs(tmpdir); + JetTestUtils.recreateDirectory(tmpdir); } @Override diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index ed43b181be0..ab08e533763 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -13,6 +13,8 @@ import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.SlicedMap; import org.jetbrains.jet.util.slicedmap.WritableSlice; +import java.io.File; +import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -128,4 +130,33 @@ public class JetTestUtils { public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { return AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, flowDataTraceFactory); } + + + public static void mkdirs(File file) throws IOException { + if (file.isDirectory()) { + return; + } + if (!file.mkdirs()) { + throw new IOException(); + } + } + + public static void rmrf(File file) { + if (file != null) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + rmrf(child); + } + } + file.delete(); + } + } + + public static void recreateDirectory(File file) throws IOException { + rmrf(file); + mkdirs(file); + } + + } diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java index e97ad3202cd..5deb55ba672 100644 --- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -65,8 +65,7 @@ public class ReadClassDataTest extends UsefulTestCase { protected void setUp() throws Exception { super.setUp(); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); - rmrf(tmpdir); - mkdirs(tmpdir); + JetTestUtils.recreateDirectory(tmpdir); } @Override @@ -74,27 +73,6 @@ public class ReadClassDataTest extends UsefulTestCase { Disposer.dispose(myTestRootDisposable); } - private void mkdirs(File file) throws IOException { - if (file.isDirectory()) { - return; - } - if (!file.mkdirs()) { - throw new IOException(); - } - } - - private void rmrf(File file) { - if (file != null) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - rmrf(child); - } - } - file.delete(); - } - } - private void createMockCoreEnvironment() { jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); From c76463256bfe65104e7a6e31e9f7b8aa8097d20c Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 7 Dec 2011 22:27:42 +0400 Subject: [PATCH 15/20] refactor tests --- .../jet/CompileJavaAgainstKotlinTest.java | 15 ++------------- .../tests/org/jetbrains/jet/JetLiteFixture.java | 5 +---- .../tests/org/jetbrains/jet/JetTestUtils.java | 10 ++++++++++ .../org/jetbrains/jet/ReadClassDataTest.java | 16 ++++++---------- 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java index 32fe6c20c93..bf1ec887eae 100644 --- a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java @@ -16,10 +16,8 @@ import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.compiler.CompileEnvironment; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; 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.plugin.JetLanguage; import org.junit.Assert; @@ -28,7 +26,6 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.File; -import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; @@ -51,14 +48,6 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { this.javaFile = new File(ktFile.getPath().replaceFirst("\\.kt", ".java")); } - private void createMockCoreEnvironment() { - jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); - - final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); - jetCoreEnvironment.addToClasspath(rtJar); - jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); - } - @Override public String getName() { return ktFile.getName(); @@ -79,14 +68,14 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { @Override protected void runTest() throws Throwable { - createMockCoreEnvironment(); + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); String text = FileUtil.loadFile(ktFile); - LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); + LightVirtualFile virtualFile = new LightVirtualFile(ktFile.getName(), JetLanguage.INSTANCE, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); diff --git a/compiler/tests/org/jetbrains/jet/JetLiteFixture.java b/compiler/tests/org/jetbrains/jet/JetLiteFixture.java index 987ee56ad2c..9ff4e21f148 100644 --- a/compiler/tests/org/jetbrains/jet/JetLiteFixture.java +++ b/compiler/tests/org/jetbrains/jet/JetLiteFixture.java @@ -53,10 +53,7 @@ public abstract class JetLiteFixture extends UsefulTestCase { } protected void createEnvironmentWithMockJdk() { - myEnvironment = new JetCoreEnvironment(getTestRootDisposable()); - final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); - myEnvironment.addToClasspath(rtJar); - myEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + myEnvironment = JetTestUtils.createEnvironmentWithMockJdk(getTestRootDisposable()); } protected void createEnvironmentWithFullJdk() { diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index ab08e533763..687c1f1a9ac 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -1,5 +1,6 @@ package org.jetbrains.jet; +import com.intellij.openapi.Disposable; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -132,6 +133,15 @@ public class JetTestUtils { } + public static JetCoreEnvironment createEnvironmentWithMockJdk(Disposable disposable) { + JetCoreEnvironment environment = new JetCoreEnvironment(disposable); + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + environment.addToClasspath(rtJar); + environment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + return environment; + } + + public static void mkdirs(File file) throws IOException { if (file.isDirectory()) { return; diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java index 5deb55ba672..0a84cae970b 100644 --- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -1,6 +1,5 @@ package org.jetbrains.jet; -import com.intellij.lang.ASTFactory; import com.intellij.lang.LanguageASTFactory; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.Disposable; @@ -35,9 +34,7 @@ import org.jetbrains.jet.plugin.JetLanguage; import org.junit.Assert; import java.io.File; -import java.io.IOException; import java.lang.reflect.Method; -import java.util.Arrays; import java.util.Set; /** @@ -83,14 +80,14 @@ public class ReadClassDataTest extends UsefulTestCase { @Override public void runTest() throws Exception { - createMockCoreEnvironment(); + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); String text = FileUtil.loadFile(testFile); - LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); + LightVirtualFile virtualFile = new LightVirtualFile(testFile.getName(), JetLanguage.INSTANCE, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); @@ -107,11 +104,10 @@ public class ReadClassDataTest extends UsefulTestCase { Assert.assertEquals("test", namespaceFromSource.getName()); Disposer.dispose(myTestRootDisposable); - - - - createMockCoreEnvironment(); - + + + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + jetCoreEnvironment.addToClasspath(tmpdir); JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject()); From 43885f0955c5e0cc0079d6125f25da7b76b3b029 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 7 Dec 2011 20:34:48 +0200 Subject: [PATCH 16/20] KT-769, KT-773 wrong compilation of when --- .../jet/codegen/ExpressionCodegen.java | 22 ++++++++++------ .../testData/codegen/regressions/kt769.jet | 11 ++++++++ .../testData/codegen/regressions/kt773.jet | 25 +++++++++++++++++++ .../jet/codegen/ControlStructuresTest.java | 10 ++++++++ 4 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt769.jet create mode 100644 compiler/testData/codegen/regressions/kt773.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9f29c28ce15..28e82ad993a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2562,13 +2562,21 @@ If finally block is present, its last expression is the value of try expression. public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) { JetExpression expr = expression.getSubjectExpression(); final Type subjectType = expressionType(expr); + final Type resultType = expressionType(expression); final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize()); gen(expr, subjectType); v.store(subjectLocal, subjectType); Label end = new Label(); - Label nextCondition = null; boolean hasElse = false; + for (JetWhenEntry whenEntry : expression.getEntries()) { + if(whenEntry.isElse()) { + hasElse = true; + break; + } + } + + Label nextCondition = null; for (JetWhenEntry whenEntry : expression.getEntries()) { if (nextCondition != null) { v.mark(nextCondition); @@ -2588,13 +2596,13 @@ If finally block is present, its last expression is the value of try expression. } } } - else { - hasElse = true; - } + v.visitLabel(thisEntry); - genToJVMStack(whenEntry.getExpression()); + gen(whenEntry.getExpression(), resultType); mark.dropTo(); - v.goTo(end); + if (!whenEntry.isElse()) { + v.goTo(end); + } } if (!hasElse && nextCondition != null) { v.mark(nextCondition); @@ -2603,7 +2611,7 @@ If finally block is present, its last expression is the value of try expression. v.mark(end); myFrameMap.leaveTemp(subjectType.getSize()); - return StackValue.onStack(expressionType(expression)); + return StackValue.onStack(resultType); } private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition, @Nullable Label nextEntry) { diff --git a/compiler/testData/codegen/regressions/kt769.jet b/compiler/testData/codegen/regressions/kt769.jet new file mode 100644 index 00000000000..266af79d867 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt769.jet @@ -0,0 +1,11 @@ +namespace w_range + +fun box() : String { + var i = 0 + when (i) { + 1 => i-- + else => { i = 2 } + } + System.out?.println(i) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/regressions/kt773.jet b/compiler/testData/codegen/regressions/kt773.jet new file mode 100644 index 00000000000..6cad8d6ae03 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt773.jet @@ -0,0 +1,25 @@ +namespace demo2 + +fun print(o : Any?) {} + +fun test(i : Int) { + var monthString : String? = "" + when (i) { + 1 => { + print(1) + print(2) + print(3) + print(4) + print(5) + } + else => { + monthString = "Invalid month" + } + } + print(monthString) +} + +fun box() : String { + for (i in 1..12) test(i) + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index a1bf84af9d6..b6f0f1b3ad5 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -221,6 +221,16 @@ public class ControlStructuresTest extends CodegenTestCase { blackBoxFile("regressions/kt434.jet"); } + public void testKt769() throws Exception { + blackBoxFile("regressions/kt769.jet"); +// System.out.println(generateToText()); + } + + public void testKt773() throws Exception { + blackBoxFile("regressions/kt773.jet"); +// System.out.println(generateToText()); + } + public void testQuicksort() throws Exception { blackBoxFile("controlStructures/quicksort.jet"); // System.out.println(generateToText()); From c6ed91610188dc3cc30f1b24cef2a38c8664b9eb Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 8 Dec 2011 04:31:36 +0400 Subject: [PATCH 17/20] fix wrong names --- .../jet/codegen/FunctionCodegen.java | 27 ++++++++-------- .../jetbrains/jet/codegen/JetTypeMapper.java | 2 ++ .../resolve/java/JavaDescriptorResolver.java | 11 ++++--- .../jet/lang/resolve/StdlibNames.java | 32 +++++++++++++++++++ 4 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 248fc165a52..ab753c1cc28 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -6,6 +6,7 @@ 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.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.StdlibNames; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.AnnotationVisitor; @@ -81,40 +82,40 @@ public class FunctionCodegen { if(v.generateCode()) { int start = 0; if(kind != OwnerKind.TRAIT_IMPL) { - AnnotationVisitor av = mv.visitAnnotation("Ljet/typeinfo/JetMethod;", true); + AnnotationVisitor av = mv.visitAnnotation(StdlibNames.JET_METHOD_TYPE.getDescriptor(), true); if(functionDescriptor.getReturnType().isNullable()) { - av.visit("nullableReturnType", true); + av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true); } av.visitEnd(); } if(kind == OwnerKind.TRAIT_IMPL) { - AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true); - av.visit("value", "this$self"); + AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true); + av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$self"); av.visitEnd(); } if(receiverParameter.exists()) { - AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true); - av.visit("value", "this$receiver"); + AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true); + av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$receiver"); if(receiverParameter.getType().isNullable()) { - av.visit("nullable", true); + av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true); } av.visitEnd(); } for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { - AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetTypeParameter;", true); - av.visit("value", typeParameterDescriptor.getName()); + AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_TYPE_PARAMETER_DESCRIPTOR, true); + av.visit(StdlibNames.JET_TYPE_PARAMETER_NAME_FIELD, typeParameterDescriptor.getName()); av.visitEnd(); } for(int i = 0; i != paramDescrs.size(); ++i) { - AnnotationVisitor av = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameter;", true); + AnnotationVisitor av = mv.visitParameterAnnotation(i + start, StdlibNames.JET_PARAMETER_DESCRIPTOR, true); ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i); - av.visit("name", parameterDescriptor.getName()); + av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, parameterDescriptor.getName()); if(parameterDescriptor.hasDefaultValue()) { - av.visit("hasDefaultValue", true); + av.visit(StdlibNames.JET_PARAMETER_HAS_DEFAULT_FIELD, true); } if(parameterDescriptor.getOutType().isNullable()) { - av.visit("nullable", true); + av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true); } av.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index da8f91a181f..fdd99201f77 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -82,6 +82,8 @@ public class JetTypeMapper { public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator"); public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator"); public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator"); + + public static final Type TYPE_JET_PARAMETER = Type.getType(JetParameter.class); public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 56b9f16b534..73a380e8260 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.StdlibNames; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.plugin.JetFileType; @@ -354,13 +355,13 @@ public class JavaDescriptorResolver { PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes(); attributes.toString(); - if (annotation.getQualifiedName().equals("jet.typeinfo.JetParameter")) { - PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue("name"); + if (annotation.getQualifiedName().equals(StdlibNames.JET_PARAMETER_CLASS)) { + PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NAME_FIELD); if (nameExpression != null) { name = (String) nameExpression.getValue(); } - PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullable"); + PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NULLABLE_FIELD); if (nullableExpression != null) { nullable = (Boolean) nullableExpression.getValue(); } else { @@ -496,8 +497,8 @@ public class JavaDescriptorResolver { boolean nullable = true; for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { - if (annotation.getQualifiedName().equals("jet.typeinfo.JetMethod")) { - PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullableReturnType"); + if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) { + PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD); if (nullableExpression != null) { nullable = (Boolean) nullableExpression.getValue(); } else { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java new file mode 100644 index 00000000000..5f54c4a96d1 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java @@ -0,0 +1,32 @@ +package org.jetbrains.jet.lang.resolve; + +import org.objectweb.asm.Type; + +/** + * @author Stepan Koltsov + */ +public class StdlibNames { + + public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetParameter"); + public static final String JET_PARAMETER_CLASS = "jet.typeinfo.JetParameter"; + public static final String JET_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetParameter;"; + + public static final String JET_PARAMETER_NAME_FIELD = "name"; + public static final String JET_PARAMETER_HAS_DEFAULT_FIELD = "hasDefault"; + public static final String JET_PARAMETER_NULLABLE_FIELD = "nullable"; + + + public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter"); + public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter"; + public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;"; + + public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name"; + + + public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod"); + public static final String JET_METHOD_CLASS = "jet.typeinfo.JetMethod"; + public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;"; + + public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType"; + +} From ec83517f8d923ff1676a77bb4a18e6c809dc474d Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 8 Dec 2011 04:31:40 +0400 Subject: [PATCH 18/20] generic signature is not needed in bridge method (signature generation code will be restored/rewritten in next commit) please review --- .../jetbrains/jet/codegen/ClosureCodegen.java | 2 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 30 ------------------- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 085dfb7f5c3..ef5faad65c5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -176,7 +176,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { if(bridge.getDescriptor().equals(delegate.getDescriptor())) return; - final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]); + final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), null, new String[0]); if (cv.generateCode()) { mv.visitCode(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index fdd99201f77..587570af1a5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -392,36 +392,6 @@ public class JetTypeMapper { return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); } - public String genericSignature(FunctionDescriptor f) { - StringBuffer answer = new StringBuffer(); - final List typeParameters = f.getTypeParameters(); - if (!typeParameters.isEmpty()) { - answer.append('<'); - for (TypeParameterDescriptor p : typeParameters) { - appendTypeParameterSignature(answer, p); - } - answer.append('>'); - } - - answer.append('('); - for (ValueParameterDescriptor p : f.getValueParameters()) { - appendType(answer, p.getOutType()); - } - answer.append(')'); - - appendType(answer, f.getReturnType()); - - return answer.toString(); - } - - private void appendType(StringBuffer answer, JetType type) { - answer.append(mapType(type).getDescriptor()); // TODO: type parameter references! - } - - private static void appendTypeParameterSignature(StringBuffer answer, TypeParameterDescriptor p) { - answer.append(p.getName()); // TODO: BOUND! - } - public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { Type returnType = mapType(descriptor.getOutType()); String name = PropertyCodegen.getterName(descriptor.getName()); From 0656f1f0e06cab676ee4877a1f80be3a930e9474 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 8 Dec 2011 04:31:44 +0400 Subject: [PATCH 19/20] writing java method signatures All tests pass, but it does not mean nothing is broken. --- .../jetbrains/jet/codegen/CallableMethod.java | 14 +- .../jetbrains/jet/codegen/ClosureCodegen.java | 6 +- .../jet/codegen/ExpressionCodegen.java | 24 +-- .../jet/codegen/FunctionCodegen.java | 26 +-- .../jet/codegen/GenerationState.java | 2 +- .../codegen/ImplementationBodyCodegen.java | 24 +-- .../jetbrains/jet/codegen/JetTypeMapper.java | 177 +++++++++++++++--- .../jet/codegen/JvmMethodSignature.java | 28 +++ .../jet/codegen/PropertyCodegen.java | 4 +- .../jet/codegen/intrinsics/PsiMethodCall.java | 2 +- .../GenericArray.java | 7 + .../compileJavaAgainstKotlin/GenericArray.kt | 1 + .../compileJavaAgainstKotlin/Hello.java | 2 +- .../compileJavaAgainstKotlin/Hello.kt | 2 +- .../compileJavaAgainstKotlin/Int.java | 6 + .../testData/compileJavaAgainstKotlin/Int.kt | 1 + .../compileJavaAgainstKotlin/IntArray.java | 6 + .../compileJavaAgainstKotlin/IntArray.kt | 1 + .../IntWithDefault.java | 6 + .../IntWithDefault.kt | 1 + .../compileJavaAgainstKotlin/ListOfInt.java | 11 ++ .../compileJavaAgainstKotlin/ListOfInt.kt | 3 + .../ListOfString.java | 9 + .../compileJavaAgainstKotlin/ListOfString.kt | 3 + .../compileJavaAgainstKotlin/ListOfT.java | 12 ++ .../compileJavaAgainstKotlin/ListOfT.kt | 3 + .../MapOfKString.java | 13 ++ .../compileJavaAgainstKotlin/MapOfKString.kt | 3 + .../MapOfStringIntQ.java | 11 ++ .../MapOfStringIntQ.kt | 3 + .../compileJavaAgainstKotlin/Void.java | 5 + .../testData/compileJavaAgainstKotlin/Void.kt | 1 + .../jet/CompileJavaAgainstKotlinTest.java | 2 +- 33 files changed, 339 insertions(+), 80 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/GenericArray.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/GenericArray.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/Int.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/Int.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/IntArray.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/IntArray.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/IntWithDefault.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/IntWithDefault.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/ListOfInt.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/ListOfInt.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/ListOfString.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/ListOfString.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/ListOfT.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/ListOfT.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/MapOfKString.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/MapOfKString.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/Void.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/Void.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java index 8f284c416fc..ffffaffb1ec 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java @@ -19,7 +19,7 @@ import java.util.List; */ public class CallableMethod implements Callable { private String owner; - private final Method signature; + private final JvmMethodSignature signature; private int invokeOpcode; private final List valueParameterTypes; private ClassDescriptor thisClass = null; @@ -27,7 +27,7 @@ public class CallableMethod implements Callable { private CallableDescriptor receiverFunction = null; private Type generateCalleeType = null; - public CallableMethod(String owner, Method signature, int invokeOpcode, List valueParameterTypes) { + public CallableMethod(String owner, JvmMethodSignature signature, int invokeOpcode, List valueParameterTypes) { this.owner = owner; this.signature = signature; this.invokeOpcode = invokeOpcode; @@ -38,7 +38,7 @@ public class CallableMethod implements Callable { return owner; } - public Method getSignature() { + public JvmMethodSignature getSignature() { return signature; } @@ -67,7 +67,7 @@ public class CallableMethod implements Callable { } void invoke(InstructionAdapter v) { - v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor()); + v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getAsmMethod().getName(), getSignature().getAsmMethod().getDescriptor()); } public void requestGenerateCallee(Type objectType) { @@ -80,14 +80,14 @@ public class CallableMethod implements Callable { public void invokeWithDefault(InstructionAdapter v, int mask) { v.iconst(mask); - String desc = getSignature().getDescriptor().replace(")", "I)"); - if("".equals(getSignature().getName())) { + String desc = getSignature().getAsmMethod().getDescriptor().replace(")", "I)"); + if("".equals(getSignature().getAsmMethod().getName())) { v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "", desc); } else { if(getInvokeOpcode() != Opcodes.INVOKESTATIC) desc = desc.replace("(", "(L" + getOwner() + ";"); - v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc); + v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getAsmMethod().getName() + "$default", desc); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index ef5faad65c5..b98897f0b03 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -53,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { public static CallableMethod asCallableMethod(FunctionDescriptor fd) { Method descriptor = erasedInvokeSignature(fd); String owner = getInternalClassName(fd); - final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); + final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); if (fd.getReceiverParameter().exists()) { result.setNeedsReceiver(fd); } @@ -62,7 +62,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { } public Method invokeSignature(FunctionDescriptor fd) { - return state.getTypeMapper().mapSignature("invoke", fd); + return state.getTypeMapper().mapSignature("invoke", fd).getAsmMethod(); } public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) { @@ -165,7 +165,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper()); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); - fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); + fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null), funDescriptor); return closureContext.outerWasUsed; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 28e82ad993a..38a87f1fcc5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -991,7 +991,7 @@ public class ExpressionCodegen extends JetVisitor { } } - v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getDescriptor()); + v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getAsmMethod().getDescriptor()); StackValue.onStack(asmType(functionDescriptor.getReturnType())).coerce(type, v); } @@ -1034,7 +1034,7 @@ public class ExpressionCodegen extends JetVisitor { } } if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) - getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION); + getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod(); else getter = null; } @@ -1043,10 +1043,12 @@ public class ExpressionCodegen extends JetVisitor { setter = null; } else { - if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) - setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION); - else + if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) { + JvmMethodSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION); + setter = jvmMethodSignature != null ? jvmMethodSignature.getAsmMethod() : null; + } else { setter = null; + } } } @@ -1119,7 +1121,7 @@ public class ExpressionCodegen extends JetVisitor { final CallableMethod callableMethod = (CallableMethod) callable; invokeMethodWithArguments(callableMethod, expression, receiver); - final Type callReturnType = callableMethod.getSignature().getReturnType(); + final Type callReturnType = callableMethod.getSignature().getAsmMethod().getReturnType(); return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType); } else { @@ -1478,7 +1480,7 @@ public class ExpressionCodegen extends JetVisitor { pushTypeArguments(resolvedCall); pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes()); callableMethod.invoke(v); - return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType()); + return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType()); } } } @@ -1850,7 +1852,7 @@ public class ExpressionCodegen extends JetVisitor { CallableMethod callableMethod = (CallableMethod) callable; genToJVMStack(expression.getBaseExpression()); callableMethod.invoke(v); - return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType()); + return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType()); } } @@ -2115,7 +2117,7 @@ public class ExpressionCodegen extends JetVisitor { else { CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, false, OwnerKind.IMPLEMENTATION); - boolean isGetter = accessor.getSignature().getName().equals("get"); + boolean isGetter = accessor.getSignature().getAsmMethod().getName().equals("get"); ResolvedCall resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); ResolvedCall resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); @@ -2124,7 +2126,7 @@ public class ExpressionCodegen extends JetVisitor { FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor(); Type asmType; - Type[] argumentTypes = accessor.getSignature().getArgumentTypes(); + Type[] argumentTypes = accessor.getSignature().getAsmMethod().getArgumentTypes(); int index = 0; if(isGetter) { Callable callable = resolveToCallable(getterDescriptor, false); @@ -2145,7 +2147,7 @@ public class ExpressionCodegen extends JetVisitor { index++; } } - asmType = accessor.getSignature().getReturnType(); + asmType = accessor.getSignature().getAsmMethod().getReturnType(); } else { assert resolvedSetCall != null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index ab753c1cc28..cb0248c318d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.StdlibNames; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeProjection; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -17,6 +18,7 @@ import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.Method; import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureWriter; +import org.objectweb.asm.util.CheckSignatureAdapter; import java.util.List; import java.util.Set; @@ -44,19 +46,19 @@ public class FunctionCodegen { public void gen(JetNamedFunction f) { final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f); assert functionDescriptor != null; - Method method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature(); + JvmMethodSignature method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature(); generateMethod(f, method, functionDescriptor); } - public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) { + public void generateMethod(JetDeclarationWithBody f, JvmMethodSignature jvmMethod, FunctionDescriptor functionDescriptor) { CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor); final JetExpression bodyExpression = f.getBodyExpression(); generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f); } - + private void generatedMethod(JetExpression bodyExpressions, - Method jvmSignature, + JvmMethodSignature jvmSignature, CodegenContext.MethodContext context, FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun) { @@ -78,7 +80,7 @@ public class FunctionCodegen { boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); if (isAbstract) flags |= ACC_ABSTRACT; - final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); + final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), jvmSignature.getGenericsSignature(), null); if(v.generateCode()) { int start = 0; if(kind != OwnerKind.TRAIT_IMPL) { @@ -128,9 +130,9 @@ public class FunctionCodegen { FrameMap frameMap = context.prepareFrame(typeMapper); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state); - Type[] argTypes = jvmSignature.getArgumentTypes(); + Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes(); int add = 0; if(kind == OwnerKind.TRAIT_IMPL) @@ -159,8 +161,8 @@ public class FunctionCodegen { Type argType = argTypes[i]; iv.load(i + 1, argType); } - iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getName(), jvmSignature.getDescriptor()); - iv.areturn(jvmSignature.getReturnType()); + iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor()); + iv.areturn(jvmSignature.getAsmMethod().getReturnType()); } else { for (ValueParameterDescriptor parameter : paramDescrs) { @@ -213,11 +215,11 @@ public class FunctionCodegen { mv.visitMaxs(0, 0); mv.visitEnd(); - generateBridgeIfNeeded(owner, state, v, jvmSignature, functionDescriptor, kind); + generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind); } } - generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind); + generateDefaultIfNeeded(context, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind); } static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { @@ -383,7 +385,7 @@ public class FunctionCodegen { Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType()); Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType()); if(!type1.equals(type2)) { - Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()); + Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod(); int flags = ACC_PUBLIC; // TODO. final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 8ddc2d7f5a1..461c528475d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -146,7 +146,7 @@ public class GenerationState { ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration); CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); - return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), objectContext.outerWasUsed, null); + return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(), objectContext.outerWasUsed, null); } public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 5a552c69372..4f80d963954 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -138,8 +138,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); - Method method = typeMapper.mapSignature(bridge.getName(), bridge); - Method originalMethod = typeMapper.mapSignature(original.getName(), original); + Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod(); + Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod(); Type[] argTypes = method.getArgumentTypes(); MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null); @@ -166,8 +166,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); - Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION); - Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); + Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod(); + Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod(); MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); InstructionAdapter iv = null; if (v.generateCode()) { @@ -186,8 +186,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { mv.visitEnd(); } - method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION); - originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); + method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod(); + originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod(); mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); if (v.generateCode()) { mv.visitCode(); @@ -283,11 +283,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } constructorMethod = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); - callableMethod = new CallableMethod("", constructorMethod, Opcodes.INVOKESPECIAL, Collections.emptyList()); + callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.emptyList()); } else { callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); - constructorMethod = callableMethod.getSignature(); + constructorMethod = callableMethod.getSignature().getAsmMethod(); } ObjectOrClosureCodegen closure = context.closure; @@ -471,7 +471,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { mv.visitMaxs(0, 0); mv.visitEnd(); - FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION ); + FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION); } private void generateTraitMethods(ExpressionCodegen codegen) { @@ -490,8 +490,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if(jetClass.isTrait()) { int flags = Opcodes.ACC_PUBLIC; // TODO. - Method function = typeMapper.mapSignature(fun.getName(), fun); - Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()); + Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod(); + Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod(); final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); if (v.generateCode()) { @@ -629,7 +629,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind); int flags = Opcodes.ACC_PUBLIC; // TODO - final MethodVisitor mv = v.newMethod(constructor, flags, "", method.getSignature().getDescriptor(), null, null); + final MethodVisitor mv = v.newMethod(constructor, flags, "", method.getSignature().getAsmMethod().getDescriptor(), null, null); if (v.generateCode()) { mv.visitCode(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 587570af1a5..3c75c794fea 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -5,6 +5,7 @@ import jet.JetObject; import jet.typeinfo.TypeInfo; import jet.typeinfo.TypeInfoProjection; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -17,6 +18,9 @@ import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; +import org.objectweb.asm.util.CheckSignatureAdapter; import java.util.*; @@ -83,8 +87,6 @@ public class JetTypeMapper { public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator"); public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator"); - public static final Type TYPE_JET_PARAMETER = Type.getType(JetParameter.class); - public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; this.bindingContext = bindingContext; @@ -153,13 +155,23 @@ public class JetTypeMapper { } @NotNull public Type mapReturnType(final JetType jetType) { + return mapReturnType(jetType, null); + } + + @NotNull private Type mapReturnType(final JetType jetType, @Nullable SignatureVisitor signatureVisitor) { if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) { + if (signatureVisitor != null) { + signatureVisitor.visitBaseType('V'); + } return Type.VOID_TYPE; } if (jetType.equals(JetStandardClasses.getNullableNothingType())) { + if (signatureVisitor != null) { + visitAsmType(signatureVisitor, TYPE_OBJECT); + } return TYPE_OBJECT; } - return mapType(jetType, OwnerKind.IMPLEMENTATION); + return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor); } private HashMap> naming = new HashMap>(); @@ -203,15 +215,28 @@ public class JetTypeMapper { return name; } - + @NotNull public Type mapType(final JetType jetType) { - return mapType(jetType, OwnerKind.IMPLEMENTATION); + return mapType(jetType, (SignatureVisitor) null); + } + + @NotNull private Type mapType(JetType jetType, @Nullable SignatureVisitor signatureVisitor) { + return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor); } @NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) { + return mapType(jetType, kind, null); + } + + @NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor) { + return mapType(jetType, kind, signatureVisitor, false); + } + + @NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor, boolean typeParameter) { Type known = knowTypes.get(jetType); - if(known != null) - return known; + if (known != null) { + return mapKnownAsmType(jetType, known, signatureVisitor, typeParameter); + } DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); if (standardLibrary.getArray().equals(descriptor)) { @@ -219,10 +244,18 @@ public class JetTypeMapper { throw new UnsupportedOperationException("arrays must have one type argument"); } JetType memberType = jetType.getArguments().get(0).getType(); - if(!isGenericsArray(jetType)) + + if (signatureVisitor != null) { + SignatureVisitor arraySignatureVisitor = signatureVisitor.visitArrayType(); + // TODO: box + mapType(memberType, kind, arraySignatureVisitor); + } + + if (!isGenericsArray(jetType)) { return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor()); - else + } else { return ARRAY_GENERIC_TYPE; + } } if (JetStandardClasses.getAny().equals(descriptor)) { @@ -230,16 +263,64 @@ public class JetTypeMapper { } if (descriptor instanceof ClassDescriptor) { + String name = getFQName(descriptor); - return Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : "")); + Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : "")); + + if (signatureVisitor != null) { + signatureVisitor.visitClassType(asmType.getInternalName()); + for (TypeProjection proj : jetType.getArguments()) { + // TODO: +- + SignatureVisitor argumentSignatureVisitor = signatureVisitor.visitTypeArgument('='); + mapType(proj.getType(), kind, argumentSignatureVisitor, true); + } + signatureVisitor.visitEnd(); + } + + return asmType; } if (descriptor instanceof TypeParameterDescriptor) { + if (signatureVisitor != null) { + TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor(); + signatureVisitor.visitTypeVariable(typeParameterDescriptor.getName()); + } + return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind); } throw new UnsupportedOperationException("Unknown type " + jetType); } + + private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable SignatureVisitor signatureVisitor, boolean genericTypeParameter) { + if (signatureVisitor != null) { + if (genericTypeParameter) { + visitAsmType(signatureVisitor, boxType(asmType)); + } else { + visitAsmType(signatureVisitor, asmType); + } + } + return asmType; + } + + private void visitAsmType(SignatureVisitor visitor, Type asmType) { + switch (asmType.getSort()) { + case Type.OBJECT: + visitor.visitClassType(asmType.getInternalName()); + visitor.visitEnd(); + return; + case Type.ARRAY: + SignatureVisitor elementSignatureVisitor = visitor.visitArrayType(); + visitAsmType(elementSignatureVisitor, asmType.getElementType()); + return; + default: + String descriptor = asmType.getDescriptor(); + if (descriptor.length() != 1) { + throw new IllegalStateException(); + } + visitor.visitBaseType(descriptor.charAt(0)); + } + } public static Type unboxType(final Type type) { if (type == JL_INTEGER_TYPE) { @@ -294,6 +375,7 @@ public class JetTypeMapper { return asmType; } + private static final boolean DEBUG_SIGNATURE_WRITER = true; public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) { if(functionDescriptor == null) @@ -301,7 +383,7 @@ public class JetTypeMapper { final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final List valueParameterTypes = new ArrayList(); - Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); + JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, valueParameterTypes, kind); String owner; int invokeOpcode; ClassDescriptor thisClass; @@ -328,7 +410,7 @@ public class JetTypeMapper { ? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE) : (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL); if(isInterface && superCall) { - descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL); + descriptor = mapSignature(functionDescriptor.getOriginal(), false, valueParameterTypes, OwnerKind.TRAIT_IMPL); } thisClass = (ClassDescriptor) functionParent; } @@ -345,7 +427,36 @@ public class JetTypeMapper { return result; } - private Method mapSignature(FunctionDescriptor f, List valueParameterTypes, OwnerKind kind) { + private JvmMethodSignature mapSignature(FunctionDescriptor f, boolean needGenericSignature, List valueParameterTypes, OwnerKind kind) { + + for (ValueParameterDescriptor valueParameterDescriptor : f.getValueParameters()) { + if (valueParameterDescriptor.hasDefaultValue()) { + // TODO + needGenericSignature = false; + } + } + + if (kind == OwnerKind.TRAIT_IMPL) { + needGenericSignature = false; + } + + SignatureWriter signatureWriter = null; + SignatureVisitor signatureVisitor = null; + if (needGenericSignature) { + signatureWriter = new SignatureWriter(); + signatureVisitor = DEBUG_SIGNATURE_WRITER ? new CheckSignatureAdapter(CheckSignatureAdapter.METHOD_SIGNATURE, signatureWriter) : signatureWriter; + } + + for (TypeParameterDescriptor typeParameterDescriptor : f.getTypeParameters()) { + if (signatureVisitor != null) { + signatureVisitor.visitFormalTypeParameter(typeParameterDescriptor.getName()); + SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound(); + // TODO: wrong base + visitAsmType(classBoundVisitor, TYPE_OBJECT); + // TODO: interfaces + } + } + final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter(); final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType(); final List parameters = f.getValueParameters(); @@ -353,32 +464,36 @@ public class JetTypeMapper { if(kind == OwnerKind.TRAIT_IMPL) { ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration(); JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext); - Type type = mapType(jetType); + Type type = mapType(jetType, signatureVisitor); if(type.getInternalName().equals("java/lang/Object")) { jetType = containingDeclaration.getDefaultType(); - type = mapType(jetType); + type = mapType(jetType, signatureVisitor); } valueParameterTypes.add(type); parameterTypes.add(type); } if (receiverType != null) { - parameterTypes.add(mapType(receiverType)); + parameterTypes.add(mapType(receiverType, signatureVisitor != null ? signatureVisitor.visitParameterType() : null)); } for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) { if(parameterDescriptor.isReified()) { parameterTypes.add(TYPE_TYPEINFO); + if (signatureVisitor != null) { + visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO); + } } } for (ValueParameterDescriptor parameter : parameters) { - Type type = mapType(parameter.getOutType()); + Type type = mapType(parameter.getOutType(), signatureVisitor != null ? signatureVisitor.visitParameterType() : null); valueParameterTypes.add(type); parameterTypes.add(type); } - Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType()); - return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); + Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null); + Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); + return new JvmMethodSignature(method, signatureWriter != null ? signatureWriter.toString() : null); } - public Method mapSignature(String name, FunctionDescriptor f) { + public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) { final ReceiverDescriptor receiver = f.getReceiverParameter(); final List parameters = f.getValueParameters(); List parameterTypes = new ArrayList(); @@ -389,10 +504,12 @@ public class JetTypeMapper { parameterTypes.add(mapType(parameter.getOutType())); } Type returnType = mapReturnType(f.getReturnType()); - return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); + // TODO: proper generic signature + return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null); } - public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { + + public JvmMethodSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { Type returnType = mapType(descriptor.getOutType()); String name = PropertyCodegen.getterName(descriptor.getName()); ArrayList params = new ArrayList(); @@ -412,10 +529,12 @@ public class JetTypeMapper { } } - return new Method(name, returnType, params.toArray(new Type[params.size()])); + // TODO: proper generic signature + return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null); } - public Method mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { + @Nullable + public JvmMethodSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { JetType inType = descriptor.getInType(); if(inType == null) return null; @@ -440,10 +559,11 @@ public class JetTypeMapper { params.add(mapType(inType)); - return new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])); + // TODO: proper generic signature + return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null); } - private Method mapConstructorSignature(ConstructorDescriptor descriptor, List valueParameterTypes) { + private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List valueParameterTypes) { List parameters = descriptor.getOriginal().getValueParameters(); List parameterTypes = new ArrayList(); ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); @@ -463,12 +583,13 @@ public class JetTypeMapper { valueParameterTypes.add(type); } - return new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); + Method method = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); + return new JvmMethodSignature(method, null); // TODO: generics signature } public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) { List valueParameterTypes = new ArrayList(); - final Method method = mapConstructorSignature(descriptor, valueParameterTypes); + final JvmMethodSignature method = mapConstructorSignature(descriptor, valueParameterTypes); String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName(); return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java new file mode 100644 index 00000000000..2dd2395c4fd --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java @@ -0,0 +1,28 @@ +package org.jetbrains.jet.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.commons.Method; + +/** + * @author Stepan Koltsov + */ +public class JvmMethodSignature { + + private final Method asmMethod; + /** Null when we don't care about type parameters */ + private final String genericsSignature; + + public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature) { + this.asmMethod = asmMethod; + this.genericsSignature = genericsSignature; + } + + public Method getAsmMethod() { + return asmMethod; + } + + public String getGenericsSignature() { + return genericsSignature; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 2ec13c784e8..dc05e02b32d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -133,7 +133,7 @@ public class PropertyCodegen { if(isTrait && !(kind instanceof OwnerKind.DelegateKind)) flags |= Opcodes.ACC_ABSTRACT; - final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor(); + final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor(); String getterName = getterName(propertyDescriptor.getName()); MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null); if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { @@ -179,7 +179,7 @@ public class PropertyCodegen { if(isTrait && !(kind instanceof OwnerKind.DelegateKind)) flags |= Opcodes.ACC_ABSTRACT; - final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor(); + final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor(); MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null); if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { mv.visitCode(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java index ca76cd1e008..d7681a08590 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java @@ -29,6 +29,6 @@ public class PsiMethodCall implements IntrinsicMethod { List arguments, StackValue receiver) { final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, false, OwnerKind.IMPLEMENTATION); codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver); - return StackValue.onStack(callableMethod.getSignature().getReturnType()); + return StackValue.onStack(callableMethod.getSignature().getAsmMethod().getReturnType()); } } diff --git a/compiler/testData/compileJavaAgainstKotlin/GenericArray.java b/compiler/testData/compileJavaAgainstKotlin/GenericArray.java new file mode 100644 index 00000000000..2ed0facc0ef --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/GenericArray.java @@ -0,0 +1,7 @@ + +class GenericArray { + public static void ggff() { + jet.typeinfo.TypeInfo noise = null; + String[] s = namespace.ffgg(noise, new String[0]); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/GenericArray.kt b/compiler/testData/compileJavaAgainstKotlin/GenericArray.kt new file mode 100644 index 00000000000..9c997ac2807 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/GenericArray.kt @@ -0,0 +1 @@ +fun

ffgg(a: Array

) = a diff --git a/compiler/testData/compileJavaAgainstKotlin/Hello.java b/compiler/testData/compileJavaAgainstKotlin/Hello.java index 4b1fd44184c..8b2af4171aa 100644 --- a/compiler/testData/compileJavaAgainstKotlin/Hello.java +++ b/compiler/testData/compileJavaAgainstKotlin/Hello.java @@ -1,6 +1,6 @@ class Hello { public static void xx() { - int x = namespace.f(); + String s = namespace.f(); } } diff --git a/compiler/testData/compileJavaAgainstKotlin/Hello.kt b/compiler/testData/compileJavaAgainstKotlin/Hello.kt index 294b46ba1d1..46dbfe4fe39 100644 --- a/compiler/testData/compileJavaAgainstKotlin/Hello.kt +++ b/compiler/testData/compileJavaAgainstKotlin/Hello.kt @@ -1 +1 @@ -fun f() = 1 +fun f() = "hello" diff --git a/compiler/testData/compileJavaAgainstKotlin/Int.java b/compiler/testData/compileJavaAgainstKotlin/Int.java new file mode 100644 index 00000000000..805aa27e075 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/Int.java @@ -0,0 +1,6 @@ + +class Int { + { + int r = namespace.lll(1); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/Int.kt b/compiler/testData/compileJavaAgainstKotlin/Int.kt new file mode 100644 index 00000000000..c6bf5becc49 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/Int.kt @@ -0,0 +1 @@ +fun lll(a: Int) = a diff --git a/compiler/testData/compileJavaAgainstKotlin/IntArray.java b/compiler/testData/compileJavaAgainstKotlin/IntArray.java new file mode 100644 index 00000000000..e0bdaa635ee --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/IntArray.java @@ -0,0 +1,6 @@ + +class IntArray { + { + int[] r = namespace.doNothing(new int[0]); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/IntArray.kt b/compiler/testData/compileJavaAgainstKotlin/IntArray.kt new file mode 100644 index 00000000000..2abd2b34c5a --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/IntArray.kt @@ -0,0 +1 @@ +fun doNothing(array: IntArray) = array diff --git a/compiler/testData/compileJavaAgainstKotlin/IntWithDefault.java b/compiler/testData/compileJavaAgainstKotlin/IntWithDefault.java new file mode 100644 index 00000000000..cc2b01c1703 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/IntWithDefault.java @@ -0,0 +1,6 @@ + +class IntWithDefault { + { + int r = namespace.www(1); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/IntWithDefault.kt b/compiler/testData/compileJavaAgainstKotlin/IntWithDefault.kt new file mode 100644 index 00000000000..260a24d9e8d --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/IntWithDefault.kt @@ -0,0 +1 @@ +fun www(p: Int = 1) = p diff --git a/compiler/testData/compileJavaAgainstKotlin/ListOfInt.java b/compiler/testData/compileJavaAgainstKotlin/ListOfInt.java new file mode 100644 index 00000000000..ed085a154c5 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/ListOfInt.java @@ -0,0 +1,11 @@ +import java.util.List; +import java.util.ArrayList; + +class ListOfInt { + + public static void hhh() { + List list = new ArrayList(); + List r = namespace.ggg(list); + } + +} diff --git a/compiler/testData/compileJavaAgainstKotlin/ListOfInt.kt b/compiler/testData/compileJavaAgainstKotlin/ListOfInt.kt new file mode 100644 index 00000000000..68a378b4013 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/ListOfInt.kt @@ -0,0 +1,3 @@ +import java.util.List + +fun ggg(list: List) = list diff --git a/compiler/testData/compileJavaAgainstKotlin/ListOfString.java b/compiler/testData/compileJavaAgainstKotlin/ListOfString.java new file mode 100644 index 00000000000..371600f2eba --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/ListOfString.java @@ -0,0 +1,9 @@ +import java.util.List; +import java.util.ArrayList; + +class ListString { + public static void gg() { + List list = new ArrayList(); + namespace.ff(list); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/ListOfString.kt b/compiler/testData/compileJavaAgainstKotlin/ListOfString.kt new file mode 100644 index 00000000000..96574032154 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/ListOfString.kt @@ -0,0 +1,3 @@ +import java.util.List + +fun ff(p: List) = 1 diff --git a/compiler/testData/compileJavaAgainstKotlin/ListOfT.java b/compiler/testData/compileJavaAgainstKotlin/ListOfT.java new file mode 100644 index 00000000000..571498c8eb9 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/ListOfT.java @@ -0,0 +1,12 @@ +import java.util.List; +import java.util.ArrayList; + +class ListOfT { + + public static void check() { + jet.typeinfo.TypeInfo nobodyCaresAboutTypeinfo = null; + List list = new ArrayList(); + List r = namespace.listOfT(nobodyCaresAboutTypeinfo, list); + } + +} diff --git a/compiler/testData/compileJavaAgainstKotlin/ListOfT.kt b/compiler/testData/compileJavaAgainstKotlin/ListOfT.kt new file mode 100644 index 00000000000..c9a6722ad16 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/ListOfT.kt @@ -0,0 +1,3 @@ +import java.util.List + +fun

listOfT(list: List

) = list diff --git a/compiler/testData/compileJavaAgainstKotlin/MapOfKString.java b/compiler/testData/compileJavaAgainstKotlin/MapOfKString.java new file mode 100644 index 00000000000..d5624e44fd7 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/MapOfKString.java @@ -0,0 +1,13 @@ +import java.util.Map; +import java.util.HashMap; +import java.math.BigDecimal; + +class MapOfKString { + public static void gfgdgfg() { + jet.typeinfo.TypeInfo useless = null; + + Map map = new HashMap(); + + Map r = namespace.fff(useless, map); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/MapOfKString.kt b/compiler/testData/compileJavaAgainstKotlin/MapOfKString.kt new file mode 100644 index 00000000000..3ec40cc8f4b --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/MapOfKString.kt @@ -0,0 +1,3 @@ +import java.util.Map + +fun fff(map: Map) = map diff --git a/compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.java b/compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.java new file mode 100644 index 00000000000..47714ce496f --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.java @@ -0,0 +1,11 @@ +import java.util.Map; +import java.util.HashMap; +import java.math.BigDecimal; + +class MapOfKString { + public static void gfgdgfg() { + Map map = new HashMap(); + + Map r = namespace.fff(map); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.kt b/compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.kt new file mode 100644 index 00000000000..b9f78cd4c89 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/MapOfStringIntQ.kt @@ -0,0 +1,3 @@ +import java.util.Map + +fun fff(map: Map) = map diff --git a/compiler/testData/compileJavaAgainstKotlin/Void.java b/compiler/testData/compileJavaAgainstKotlin/Void.java new file mode 100644 index 00000000000..67e3ab812e3 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/Void.java @@ -0,0 +1,5 @@ +class Void { + { + namespace.f(); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/Void.kt b/compiler/testData/compileJavaAgainstKotlin/Void.kt new file mode 100644 index 00000000000..119058ec2d9 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/Void.kt @@ -0,0 +1 @@ +fun f() { } diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java index bf1ec887eae..3121cfc8315 100644 --- a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java @@ -95,7 +95,7 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase { try { Iterable javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(Collections.singleton(javaFile)); List options = Arrays.asList( - "-classpath", tmpdir.getPath(), + "-classpath", tmpdir.getPath() + System.getProperty("path.separator") + "out/production/stdlib", "-d", tmpdir.getPath() ); JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, javaFileObjectsFromFiles); From b89956f1fd4f2c1dca8350f027ce105309180473 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Thu, 8 Dec 2011 11:18:27 +0200 Subject: [PATCH 20/20] LockPerf benchmark and related fixes (try/break/continue interoperability) --- .../jet/codegen/ExpressionCodegen.java | 131 +++++++++++++----- .../testData/codegen/regressions/kt496.jet | 36 +++++ examples/src/benchmarks/LockPerf.java | 43 ++++++ examples/src/benchmarks/LockPerf.kt | 55 ++++++++ 4 files changed, 228 insertions(+), 37 deletions(-) create mode 100644 examples/src/benchmarks/LockPerf.java create mode 100644 examples/src/benchmarks/LockPerf.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 38a87f1fcc5..a24e486308e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -43,9 +43,6 @@ public class ExpressionCodegen extends JetVisitor { private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException"; private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException"; - private final Stack