From b9f39b00c013092de44a4c87d083e0c5e5166002 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 28 Nov 2011 14:36:57 +0200 Subject: [PATCH 1/6] KotlinCompiler and tests aware on standard library --- build.xml | 25 +++++++- .../jet/compiler/CompileEnvironment.java | 59 ++++++++++--------- .../jet/compiler/CompileSession.java | 43 +++++++++++--- .../org/jetbrains/jet/cli/KotlinCompiler.java | 8 ++- compiler/testData/compiler/smoke/Smoke.kt | 3 + compiler/tests/compiler-tests.iml | 1 + .../jet/codegen/CodegenTestCase.java | 6 ++ .../org/jetbrains/jet/codegen/StdlibTest.java | 30 ++++++---- .../jet/compiler/CompileEnvironmentTest.java | 33 +++++++++-- stdlib/ktSrc/JavaUtil.kt | 11 ++++ stdlib/ktSrc/StandardLibrary.kt | 10 ---- 11 files changed, 161 insertions(+), 68 deletions(-) create mode 100644 stdlib/ktSrc/JavaUtil.kt diff --git a/build.xml b/build.xml index 6c91c946fa5..c799c56523e 100644 --- a/build.xml +++ b/build.xml @@ -9,6 +9,11 @@ + + + + + @@ -26,9 +31,21 @@ - + + + + + + + + + + + + + @@ -49,7 +66,11 @@ - + + + + + diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java index d2ba73c02ef..63ac39601d1 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -5,7 +5,9 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; import com.intellij.util.Function; import com.intellij.util.Processor; import jet.modules.IModuleBuilder; @@ -22,6 +24,8 @@ import java.io.*; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.jar.*; @@ -53,14 +57,18 @@ public class CompileEnvironment { } public boolean initializeKotlinRuntime() { + return initializeKotlinRuntime(myEnvironment); + } + + public static boolean initializeKotlinRuntime(JetCoreEnvironment environment) { final File unpackedRuntimePath = getUnpackedRuntimePath(); if (unpackedRuntimePath != null) { - myEnvironment.addToClasspath(unpackedRuntimePath); + environment.addToClasspath(unpackedRuntimePath); } else { final File runtimeJarPath = getRuntimeJarPath(); if (runtimeJarPath != null && runtimeJarPath.exists()) { - myEnvironment.addToClasspath(runtimeJarPath); + environment.addToClasspath(runtimeJarPath); } else { return false; @@ -147,7 +155,7 @@ public class CompileEnvironment { return null; } - public void compileModuleScript(String moduleFile) { + public void compileModuleScript(String moduleFile, String jarPath, boolean jarRuntime) { final IModuleSetBuilder moduleSetBuilder = loadModuleScript(moduleFile); if (moduleSetBuilder == null) { return; @@ -156,9 +164,9 @@ public class CompileEnvironment { final String directory = new File(moduleFile).getParent(); for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) { ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory); - final String path = new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(); + final String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(); try { - writeToJar(moduleFactory, new FileOutputStream(path), null, true); + writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime); } catch (FileNotFoundException e) { throw new CompileEnvironmentException("Invalid jar path " + path, e); } @@ -168,25 +176,7 @@ public class CompileEnvironment { public IModuleSetBuilder loadModuleScript(String moduleFile) { CompileSession scriptCompileSession = new CompileSession(myEnvironment); scriptCompileSession.addSources(moduleFile); - - URL url = CompileEnvironment.class.getClassLoader().getResource("ModuleBuilder.kt"); - if (url != null) { - String path = url.getPath(); - if (path.startsWith("file:")) { - path = path.substring(5); - } - final VirtualFile vFile = myEnvironment.getJarFileSystem().findFileByPath(path); - if (vFile == null) { - throw new CompileEnvironmentException("Couldn't load ModuleBuilder.kt from runtime jar: "+ url); - } - scriptCompileSession.addSources(vFile); - } - else { - // building from source - final String homeDirectory = getHomeDirectory(); - final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt"); - scriptCompileSession.addSources(myEnvironment.getLocalFileSystem().findFileByPath(file.getPath())); - } + scriptCompileSession.addStdLibSources(); if (!scriptCompileSession.analyze(myErrorStream)) { return null; @@ -223,6 +213,7 @@ public class CompileEnvironment { public ClassFileFactory compileModule(IModuleBuilder moduleBuilder, String directory) { CompileSession moduleCompileSession = new CompileSession(myEnvironment); + moduleCompileSession.addStdLibSources(); for (String sourceFile : moduleBuilder.getSourceFiles()) { moduleCompileSession.addSources(new File(directory, sourceFile).getPath()); } @@ -249,10 +240,21 @@ public class CompileEnvironment { mainAttributes.putValue("Main-Class", mainClass); } JarOutputStream stream = new JarOutputStream(fos, manifest); + List sanitized = Arrays.asList("kotlin/", "std/"); try { for (String file : factory.files()) { - stream.putNextEntry(new JarEntry(file)); - stream.write(factory.asBytes(file)); + boolean skip = false; + for (String prefix : sanitized) { + if(file.startsWith(prefix)) { + skip = true; + break; + } + } + + if(!skip) { + stream.putNextEntry(new JarEntry(file)); + stream.write(factory.asBytes(file)); + } } if (includeRuntime) { writeRuntimeToJar(stream); @@ -316,7 +318,7 @@ public class CompileEnvironment { } } - public void compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir) { + public void compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) { CompileSession session = new CompileSession(myEnvironment); session.addSources(sourceFileOrDir); @@ -334,7 +336,7 @@ public class CompileEnvironment { ClassFileFactory factory = session.generate(); if (jar != null) { try { - writeToJar(factory, new FileOutputStream(jar), mainClass, true); + writeToJar(factory, new FileOutputStream(jar), mainClass, includeRuntime); } catch (FileNotFoundException e) { throw new CompileEnvironmentException("Invalid jar path " + jar, e); } @@ -358,5 +360,4 @@ public class CompileEnvironment { } } } - } diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java index e90fda9eb8a..91a0dccaf9e 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java @@ -16,6 +16,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; import org.jetbrains.jet.plugin.JetFileType; +import java.io.File; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; @@ -47,7 +48,22 @@ public class CompileSession { return; } - addSources(vFile); + addSources(new File(path)); + } + + private void addSources(File file) { + if(file.isDirectory()) { + for (File child : file.listFiles()) { + addSources(child); + } + } + else { + VirtualFile fileByPath = myEnvironment.getLocalFileSystem().findFileByPath(file.getAbsolutePath()); + PsiFile psiFile = PsiManager.getInstance(myEnvironment.getProject()).findFile(fileByPath); + if(psiFile instanceof JetFile) { + mySourceFileNamespaces.add(((JetFile) psiFile).getRootNamespace()); + } + } } public void addSources(VirtualFile vFile) { @@ -66,13 +82,6 @@ public class CompileSession { } } - public void addLibrarySources(VirtualFile vFile) { - PsiFile psiFile = PsiManager.getInstance(myEnvironment.getProject()).findFile(vFile); - if (psiFile instanceof JetFile) { - myLibrarySourceFileNamespaces.add(((JetFile) psiFile).getRootNamespace()); - } - } - public List getSourceFileNamespaces() { return mySourceFileNamespaces; } @@ -104,4 +113,22 @@ public class CompileSession { generationState.compileCorrectNamespaces(myBindingContext, mySourceFileNamespaces); return generationState.createText(); } + + public boolean addStdLibSources() { + final File unpackedRuntimePath = CompileEnvironment.getUnpackedRuntimePath(); + if (unpackedRuntimePath != null) { + addSources(new File(unpackedRuntimePath, "../../../stdlib/ktSrc").getAbsoluteFile()); + } + else { + final File runtimeJarPath = CompileEnvironment.getRuntimeJarPath(); + if (runtimeJarPath != null && runtimeJarPath.exists()) { + // todo + throw new UnsupportedOperationException("Loading of stdlib sources from jar"); + } + else { + return false; + } + } + return true; + } } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 00b8cb1e85b..56db85a522d 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -23,6 +23,8 @@ public class KotlinCompiler { public String src; @Argument(value = "module", description = "module to compile") public String module; + @Argument(value = "includeRuntime", description = "include Kotlin runtime in to resulting jar") + public boolean includeRuntime; } public static void main(String[] args) { @@ -32,7 +34,7 @@ public class KotlinCompiler { Args.parse(arguments, args); } catch (Throwable t) { - System.out.println("Usage: KotlinCompiler [-output |-jar ] -src "); + System.out.println("Usage: KotlinCompiler [-output |-jar ] [-src |-module ] [-includeRuntime]"); t.printStackTrace(); return; } @@ -47,11 +49,11 @@ public class KotlinCompiler { } if (arguments.module != null) { - environment.compileModuleScript(arguments.module); + environment.compileModuleScript(arguments.module, arguments.jar, arguments.includeRuntime); return; } else { - environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir); + environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime); } } catch (CompileEnvironmentException e) { System.out.println(e.getMessage()); diff --git a/compiler/testData/compiler/smoke/Smoke.kt b/compiler/testData/compiler/smoke/Smoke.kt index 6da801d1fde..d41ccce56b7 100644 --- a/compiler/testData/compiler/smoke/Smoke.kt +++ b/compiler/testData/compiler/smoke/Smoke.kt @@ -1,4 +1,7 @@ namespace Smoke +import std.io.* + fun main(args: Array) { + print(args) } diff --git a/compiler/tests/compiler-tests.iml b/compiler/tests/compiler-tests.iml index d1dadb8a16b..05bb0565855 100644 --- a/compiler/tests/compiler-tests.iml +++ b/compiler/tests/compiler-tests.iml @@ -11,6 +11,7 @@ + diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 485a97b80d2..09f1485d650 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -1,6 +1,10 @@ package org.jetbrains.jet.codegen; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.lang.psi.JetFile; @@ -9,6 +13,8 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.parsing.JetParsingTest; import org.junit.Assert; +import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java index 7337274caac..cd1bb67e1c3 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java @@ -6,6 +6,7 @@ import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; +import org.jetbrains.jet.compiler.CompileEnvironment; import org.jetbrains.jet.compiler.CompileSession; import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; @@ -30,8 +31,8 @@ public class StdlibTest extends CodegenTestCase { session.addSources(myFile.getVirtualFile()); try { - session.addSources(addStdLib()); - } catch (IOException e) { + session.addStdLibSources(); + } catch (Throwable e) { throw new RuntimeException(e); } @@ -45,9 +46,9 @@ public class StdlibTest extends CodegenTestCase { protected ClassFileFactory generateClassesInFile() { try { CompileSession session = new CompileSession(myEnvironment); - + CompileEnvironment.initializeKotlinRuntime(myEnvironment); session.addSources(myFile.getVirtualFile()); - session.addSources(addStdLib()); + session.addStdLibSources(); if (!session.analyze(System.out)) { return null; @@ -57,18 +58,11 @@ public class StdlibTest extends CodegenTestCase { } catch (RuntimeException e) { System.out.println(generateToText()); throw e; - } catch (IOException e) { + } catch (Throwable e) { throw new RuntimeException(e); } } - private VirtualFile addStdLib() throws IOException { - String text = FileUtil.loadFile(new File(JetParsingTest.getTestDataDir() + "/../../stdlib/ktSrc/StandardLibrary.kt"), CharsetToolkit.UTF8).trim(); - text = StringUtil.convertLineSeparators(text); - PsiFile stdLibFile = createFile("StandardLibrary.kt", text); - return stdLibFile.getVirtualFile(); - } - public void testInputStreamIterator () { blackBoxFile("inputStreamIterator.jet"); // System.out.println(generateToText()); @@ -85,4 +79,16 @@ public class StdlibTest extends CodegenTestCase { public void testKt528 () { blackBoxFile("regressions/kt528.kt"); } + + public void testCollectionSize () throws Exception { + loadText("import std.util.*; fun box() = if(java.util.Arrays.asList(0, 1, 2)?.size == 3) \"OK\" else \"fail\""); +// System.out.println(generateToText()); + blackBox(); + } + + public void testCollectionEmpty () throws Exception { + loadText("import std.util.*; fun box() = if(java.util.Arrays.asList(0, 1, 2)?.empty ?: false) \"OK\" else \"fail\""); +// System.out.println(generateToText()); + blackBox(); + } } diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java index 4b01efe9efd..bb96b43f203 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java @@ -3,20 +3,20 @@ package org.jetbrains.jet.compiler; import jet.modules.IModuleBuilder; import jet.modules.IModuleSetBuilder; import junit.framework.TestCase; +import org.jetbrains.jet.cli.KotlinCompiler; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.parsing.JetParsingTest; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; /** * @author yole + * @author alex.tkachman */ public class CompileEnvironmentTest extends TestCase { private CompileEnvironment environment; @@ -51,6 +51,31 @@ public class CompileEnvironmentTest extends TestCase { assertTrue(entries.contains("Smoke/namespace.class")); } + public void testSmokeWithCompiler() throws IOException { + File tempFile = File.createTempFile("compilerTest", "compilerTest"); + try { + KotlinCompiler.main(Arrays.asList("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", "-jar", tempFile.getAbsolutePath()).toArray(new String[0])); + FileInputStream fileInputStream = new FileInputStream(tempFile); + try { + JarInputStream is = new JarInputStream(fileInputStream); + try { + final List entries = listEntries(is); + assertTrue(entries.contains("Smoke/namespace.class")); + assertEquals(1, entries.size()); + } + finally { + is.close(); + } + } + finally { + fileInputStream.close(); + } + } + finally { + tempFile.delete(); + } + } + private List listEntries(JarInputStream is) throws IOException { List entries = new ArrayList(); while (true) { diff --git a/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt new file mode 100644 index 00000000000..ba3c74b8adb --- /dev/null +++ b/stdlib/ktSrc/JavaUtil.kt @@ -0,0 +1,11 @@ +namespace std + +namespace util { + import java.util.* + + val Collection<*>.size : Int + get() = size() + + val Collection<*>.empty : Boolean + get() = isEmpty() +} \ No newline at end of file diff --git a/stdlib/ktSrc/StandardLibrary.kt b/stdlib/ktSrc/StandardLibrary.kt index 53d594e313a..999cecbad2c 100644 --- a/stdlib/ktSrc/StandardLibrary.kt +++ b/stdlib/ktSrc/StandardLibrary.kt @@ -1,15 +1,5 @@ namespace std -namespace util { - import java.util.* - - val Collection.size : Int - get() = size() - - val Collection.empty : Boolean - get() = isEmpty() -} - namespace io { import java.io.* import java.nio.charset.* From afd8981c003bb9cc39d17fff98e310f52dc643f2 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 28 Nov 2011 14:51:12 +0200 Subject: [PATCH 2/6] do not write compiled stdlib in to output dir --- .../jet/compiler/CompileEnvironment.java | 35 +++++++++++-------- .../jet/compiler/CompileEnvironmentTest.java | 27 +++++++++++++- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java index 63ac39601d1..669bda88f70 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -230,6 +230,17 @@ public class CompileEnvironment { return new File(PathManager.getResourceRoot(CompileEnvironment.class, "/org/jetbrains/jet/compiler/CompileEnvironment.class")).getParentFile().getParentFile().getParent(); } + private static final List sanitized = Arrays.asList("kotlin/", "std/"); + public static boolean skipFile(String name) { + boolean skip = false; + for (String prefix : sanitized) { + if(name.startsWith(prefix)) { + return true; + } + } + return false; + } + public static void writeToJar(ClassFileFactory factory, final OutputStream fos, @Nullable String mainClass, boolean includeRuntime) { try { Manifest manifest = new Manifest(); @@ -240,18 +251,9 @@ public class CompileEnvironment { mainAttributes.putValue("Main-Class", mainClass); } JarOutputStream stream = new JarOutputStream(fos, manifest); - List sanitized = Arrays.asList("kotlin/", "std/"); try { for (String file : factory.files()) { - boolean skip = false; - for (String prefix : sanitized) { - if(file.startsWith(prefix)) { - skip = true; - break; - } - } - - if(!skip) { + if(!skipFile(file)) { stream.putNextEntry(new JarEntry(file)); stream.write(factory.asBytes(file)); } @@ -321,6 +323,7 @@ public class CompileEnvironment { public void compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) { CompileSession session = new CompileSession(myEnvironment); session.addSources(sourceFileOrDir); + session.addStdLibSources(); String mainClass = null; for (JetNamespace namespace : session.getSourceFileNamespaces()) { @@ -352,11 +355,13 @@ public class CompileEnvironment { private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) { List files = factory.files(); for (String file : files) { - File target = new File(outputDir, file); - try { - FileUtil.writeToFile(target, factory.asBytes(file)); - } catch (IOException e) { - throw new CompileEnvironmentException(e); + if(!skipFile(file)) { + File target = new File(outputDir, file); + try { + FileUtil.writeToFile(target, factory.asBytes(file)); + } catch (IOException e) { + throw new CompileEnvironmentException(e); + } } } } diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java index bb96b43f203..41ec6729100 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java @@ -51,7 +51,7 @@ public class CompileEnvironmentTest extends TestCase { assertTrue(entries.contains("Smoke/namespace.class")); } - public void testSmokeWithCompiler() throws IOException { + public void testSmokeWithCompilerJar() throws IOException { File tempFile = File.createTempFile("compilerTest", "compilerTest"); try { KotlinCompiler.main(Arrays.asList("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", "-jar", tempFile.getAbsolutePath()).toArray(new String[0])); @@ -76,6 +76,31 @@ public class CompileEnvironmentTest extends TestCase { } } + private static void delete(File file) { + if(file.isDirectory()) { + for (File child : file.listFiles()) { + delete(child); + } + } + + file.delete(); + } + + public void testSmokeWithCompilerOutput() throws IOException { + File tempFile = File.createTempFile("compilerTest", "compilerTest"); + tempFile.delete(); + tempFile = new File(tempFile.getAbsolutePath()); + tempFile.mkdir(); + try { + KotlinCompiler.main(Arrays.asList("-src", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kt", "-output", tempFile.getAbsolutePath()).toArray(new String[0])); + assertEquals(1, tempFile.listFiles().length); + assertEquals(1, tempFile.listFiles()[0].listFiles().length); + } + finally { + delete(tempFile); + } + } + private List listEntries(JarInputStream is) throws IOException { List entries = new ArrayList(); while (true) { From 690efbb39a2e4f02cae84b76b5ae610f1675a911 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 28 Nov 2011 17:06:22 +0400 Subject: [PATCH 3/6] KT-552 For variable unresolved if loop body is not block === for(index in 0..9) x[index] = index.byt // <-- index is inresolved here === --- .../types/expressions/ControlStructureTypingVisitor.java | 3 ++- .../quick/control/ForWithoutBraces.jet | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/checkerWithErrorTypes/quick/control/ForWithoutBraces.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index d260b7ef9e3..a9a48119c7b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -216,7 +216,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { JetExpression body = expression.getBody(); if (body != null) { - facade.getType(body, context.replaceScope(loopScope)); + ExpressionTypingInternals blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(loopScope); + blockLevelVisitor.getType(body, context.replaceScope(loopScope)); } return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); diff --git a/compiler/testData/checkerWithErrorTypes/quick/control/ForWithoutBraces.jet b/compiler/testData/checkerWithErrorTypes/quick/control/ForWithoutBraces.jet new file mode 100644 index 00000000000..d79dd7e77e0 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/control/ForWithoutBraces.jet @@ -0,0 +1,8 @@ +// http://youtrack.jetbrains.net/issue/KT-552 +// KT-552 For variable unresolved if loop body is not block + +fun ff() { + var i = 1 + for (j in 1..10) + i += j +} From a9c4073f8cca0b3067f0f9e7486ba67876807956 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 28 Nov 2011 15:12:09 +0200 Subject: [PATCH 4/6] test for unreproducable KT-640 --- .../testData/codegen/regressions/kt640.jet | 29 +++++++++++++++++++ .../jetbrains/jet/codegen/ObjectGenTest.java | 4 +++ .../jet/compiler/CompileEnvironmentTest.java | 9 +++--- 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt640.jet diff --git a/compiler/testData/codegen/regressions/kt640.jet b/compiler/testData/codegen/regressions/kt640.jet new file mode 100644 index 00000000000..705fc1f338c --- /dev/null +++ b/compiler/testData/codegen/regressions/kt640.jet @@ -0,0 +1,29 @@ +namespace demo + +public open class Identifier(myName : T?, myHasDollar : Boolean) { + { + $myName = myName + $myHasDollar = myHasDollar + } + + private val myName : T? + private var myHasDollar : Boolean + private var myNullable : Boolean = true + + open public fun getName() : T? { + return myName + } + + class object { + open public fun init(name : T?) : Identifier { + val __ = Identifier(name, false) + return __ + } + } +} + +fun box() : String { + var i3 : Identifier<*>? = Identifier.init("name") + System.out?.println("Hello, " + i3?.getName()) + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index 05c5a66ca93..d8eb251833e 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -25,4 +25,8 @@ public class ObjectGenTest extends CodegenTestCase { public void testKt560() throws Exception { blackBoxFile("regressions/kt560.jet"); } + + public void testKt640() throws Exception { + blackBoxFile("regressions/kt640.jet"); + } } diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java index 41ec6729100..520dee18d48 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java @@ -76,14 +76,15 @@ public class CompileEnvironmentTest extends TestCase { } } - private static void delete(File file) { + private static boolean delete(File file) { + boolean success = true; if(file.isDirectory()) { for (File child : file.listFiles()) { - delete(child); + success = success && delete(child); } } - file.delete(); + return file.delete() && success; } public void testSmokeWithCompilerOutput() throws IOException { @@ -101,7 +102,7 @@ public class CompileEnvironmentTest extends TestCase { } } - private List listEntries(JarInputStream is) throws IOException { + private static List listEntries(JarInputStream is) throws IOException { List entries = new ArrayList(); while (true) { final JarEntry jarEntry = is.getNextJarEntry(); From 709e4b3561fafd4d54488a922e33de244c5a96b2 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 28 Nov 2011 17:54:45 +0400 Subject: [PATCH 5/6] move TaskPrioritizer.isLocal to DescriptorUtils --- .../jet/lang/resolve/DescriptorUtils.java | 31 ++++++++++++++++ .../lang/resolve/calls/TaskPrioritizer.java | 36 ++----------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index ba492a83cde..c66af6e8f03 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -123,4 +123,35 @@ public class DescriptorUtils { } return NO_RECEIVER; } + + /** + * The primary case for local extensions is the following: + * + * I had a locally declared extension function or a local variable of function type called foo + * And I called it on my x + * Now, someone added function foo() to the class of x + * My code should not change + * + * thus + * + * local extension prevail over members (and members prevail over all non-local extensions) + */ + public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) { + if (candidate instanceof ValueParameterDescriptor) { + return true; + } + DeclarationDescriptor parent = candidate.getContainingDeclaration(); + if (!(parent instanceof FunctionDescriptor)) { + return false; + } + FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent; + DeclarationDescriptor current = containerOfTheCurrentLocality; + while (current != null) { + if (current == functionDescriptor) { + return true; + } + current = current.getContainingDeclaration(); + } + return false; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java index 872781fb28b..823666d4ed2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java @@ -5,12 +5,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetSuperExpression; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastService; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; @@ -36,7 +35,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor Collection> allDescriptors, DeclarationDescriptor containerOfTheCurrentLocality, Collection> local, Collection> nonlocal) { for (ResolvedCallImpl resolvedCall : allDescriptors) { - if (isLocal(containerOfTheCurrentLocality, resolvedCall.getCandidateDescriptor())) { + if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getCandidateDescriptor())) { local.add(resolvedCall); } else { @@ -45,37 +44,6 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor } } - /** - * The primary case for local extensions is the following: - * - * I had a locally declared extension function or a local variable of function type called foo - * And I called it on my x - * Now, someone added function foo() to the class of x - * My code should not change - * - * thus - * - * local extension prevail over members (and members prevail over all non-local extensions) - */ - private static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) { - if (candidate instanceof ValueParameterDescriptor) { - return true; - } - DeclarationDescriptor parent = candidate.getContainingDeclaration(); - if (!(parent instanceof FunctionDescriptor)) { - return false; - } - FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent; - DeclarationDescriptor current = containerOfTheCurrentLocality; - while (current != null) { - if (current == functionDescriptor) { - return true; - } - current = current.getContainingDeclaration(); - } - return false; - } - @Nullable /*package*/ static JetSuperExpression getReceiverSuper(@NotNull ReceiverDescriptor receiver) { if (receiver instanceof ExpressionReceiver) { From a9a07857ded62793e80bdfd5d098f31e2315c6d0 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 28 Nov 2011 17:54:50 +0400 Subject: [PATCH 6/6] sometimes it not permitted to redeclare variable in nested scope (KT-527) --- .../jet/lang/diagnostics/Errors.java | 5 +++- .../diagnostics/RedeclarationDiagnostic.java | 14 ++++++----- .../RedeclarationDiagnosticFactory.java | 25 +++++++++++++++---- .../ControlStructureTypingVisitor.java | 13 ++++++++++ .../ExpressionTypingVisitorForStatements.java | 8 ++++++ .../ShadowParameterInFunctionBody.jet | 5 ++++ .../ShadowParameterInNestedBlockInFor.jet | 7 ++++++ .../shadowing/ShadowPropertyInClosure.jet | 3 +++ .../quick/shadowing/ShadowPropertyInFor.jet | 11 ++++++++ .../shadowing/ShadowPropertyInFunction.jet | 10 ++++++++ .../quick/shadowing/ShadowVariableInFor.jet | 6 +++++ .../shadowing/ShadowVariableInNestedBlock.jet | 7 ++++++ .../ShadowVariableInNestedClosure.jet | 5 ++++ .../ShadowVariableInNestedClosureParam.jet | 5 ++++ 14 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowParameterInFunctionBody.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowParameterInNestedBlockInFor.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInClosure.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFor.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFunction.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInFor.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedBlock.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosure.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosureParam.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 2ea2a103180..fc8ce9013f2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -44,7 +44,10 @@ public interface Errors { } }; UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = new UnresolvedReferenceDiagnosticFactory("Unresolved reference"); - RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.INSTANCE; + + RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.REDECLARATION; + RedeclarationDiagnosticFactory NAME_SHADOWING = RedeclarationDiagnosticFactory.NAME_SHADOWING; + PsiElementOnlyDiagnosticFactory2 TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); ParameterizedDiagnosticFactory1> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1>(ERROR, "Incompatible modifiers: ''{0}''") { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java index 3a8c2f02733..648c8bfe5d2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java @@ -15,8 +15,8 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR; public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement { public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl implements RedeclarationDiagnostic { - public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name) { - super(RedeclarationDiagnosticFactory.INSTANCE, ERROR, "Redeclaration: " + name, psiElement); + public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name, RedeclarationDiagnosticFactory factory) { + super(factory, factory.severity, factory.makeMessage(name), psiElement); } } @@ -24,11 +24,13 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElementp = 2 + return p +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowParameterInNestedBlockInFor.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowParameterInNestedBlockInFor.jet new file mode 100644 index 00000000000..e3e91fbe857 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowParameterInNestedBlockInFor.jet @@ -0,0 +1,7 @@ +fun f(i: Int) { + for (j in 1..100) { + { + var i = 12 + } + } +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInClosure.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInClosure.jet new file mode 100644 index 00000000000..c785e3f5fc7 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInClosure.jet @@ -0,0 +1,3 @@ +val i = 17 + +val f = { (): Int => var i = 17; i } diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFor.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFor.jet new file mode 100644 index 00000000000..e0d4766e89f --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFor.jet @@ -0,0 +1,11 @@ +class RedefinePropertyInFor() { + + var i = 1 + + fun ff() { + for (i in 0..10) { + } + } + +} + diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFunction.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFunction.jet new file mode 100644 index 00000000000..cacf415e65e --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowPropertyInFunction.jet @@ -0,0 +1,10 @@ +class RedefinePropertyInFunction() { + + var i = 17 + + fun f(): Int { + var i = 18 + return i + } + +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInFor.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInFor.jet new file mode 100644 index 00000000000..b62b6d0ea30 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInFor.jet @@ -0,0 +1,6 @@ +fun ff(): Int { + var i = 1 + for (i in 0..10) { + } + return i +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedBlock.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedBlock.jet new file mode 100644 index 00000000000..2fd755bdc1c --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedBlock.jet @@ -0,0 +1,7 @@ +fun ff(): Int { + var i = 1 + { + val i = 2 + } + return i +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosure.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosure.jet new file mode 100644 index 00000000000..d9dd9110893 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosure.jet @@ -0,0 +1,5 @@ +fun f(): Int { + var i = 17 + { (): Unit => var i = 18 } + return i +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosureParam.jet b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosureParam.jet new file mode 100644 index 00000000000..6ba5fd4c919 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/shadowing/ShadowVariableInNestedClosureParam.jet @@ -0,0 +1,5 @@ +fun ff(): Int { + var i = 1 + { (i: Int) => i } + return i +}