diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 9b9b0f88821..6756cd5a7c3 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -43,7 +43,20 @@ public class KotlinCompiler { target.println("Usage: KotlinCompiler [-output |-jar ] [-stdlib ] [-src |-module ] [-includeRuntime]"); } - public static void main(String ... args) { + public static void main(String... args) { + try { + int rc = exec(args); + if (rc != 0) { + System.err.println("exec() finished with " + rc + " return code"); + System.exit(rc); + } + } catch (CompileEnvironmentException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + } + + public static int exec(String... args) { System.setProperty("java.awt.headless", "true"); Arguments arguments = new Arguments(); try { @@ -51,18 +64,16 @@ public class KotlinCompiler { } catch (IllegalArgumentException e) { usage(System.err); - System.exit(1); - return; + return 1; } catch (Throwable t) { t.printStackTrace(); - System.exit(1); - return; + return 1; } if (arguments.help) { usage(System.out); - System.exit(0); + return 0; } CompileEnvironment environment = new CompileEnvironment(); @@ -71,22 +82,16 @@ public class KotlinCompiler { environment.setStdlib(arguments.stdlib); } - try { - if (arguments.module != null) { - environment.compileModuleScript(arguments.module, arguments.jar, arguments.includeRuntime); - return; - } - else { - if (!environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime)) { - System.exit(1); - return; - } - } - } catch (CompileEnvironmentException e) { - System.err.println(e.getMessage()); - System.exit(1); - return; + if (arguments.module != null) { + environment.compileModuleScript(arguments.module, arguments.jar, arguments.includeRuntime); + return 0; + } + else { + if (!environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime)) { + return 1; + } } - } + return 0; + } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java index 54b530da695..92a05e64133 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -22,6 +22,7 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.List; import java.util.jar.*; @@ -124,6 +125,10 @@ public class CompileEnvironment { throw new CompileEnvironmentException("Module script " + moduleFile + " compilation failed"); } + if (modules.isEmpty()) { + throw new CompileEnvironmentException("No modules where defined by " + moduleFile); + } + final String directory = new File(moduleFile).getParent(); for (Module moduleBuilder : modules) { ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory); @@ -150,7 +155,7 @@ public class CompileEnvironment { } private List runDefineModules(String moduleFile, ClassFileFactory factory) { - ClassLoader loader = myStdlib != null ? new GeneratedClassLoader(factory, new URLClassLoader(new URL[] {myStdlib})) : new GeneratedClassLoader(factory); + ClassLoader loader = myStdlib != null ? new GeneratedClassLoader(factory, new URLClassLoader(new URL[] {myStdlib}, AllModules.class.getClassLoader())) : new GeneratedClassLoader(factory); try { Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS); final Method method = namespaceClass.getDeclaredMethod("project"); @@ -161,7 +166,9 @@ public class CompileEnvironment { method.setAccessible(true); method.invoke(null); - return AllModules.modules; + ArrayList answer = new ArrayList(AllModules.modules); + AllModules.modules.clear(); + return answer; } catch (Exception e) { throw new ModuleExecutionException(e); } @@ -169,12 +176,21 @@ public class CompileEnvironment { public ClassFileFactory compileModule(Module moduleBuilder, String directory) { CompileSession moduleCompileSession = new CompileSession(myEnvironment); + + if (moduleBuilder.getSourceFiles().isEmpty()) { + throw new CompileEnvironmentException("No source files where defined"); + } + for (String sourceFile : moduleBuilder.getSourceFiles()) { File source = new File(sourceFile); if (!source.isAbsolute()) { source = new File(directory, sourceFile); } + if (!source.exists()) { + throw new CompileEnvironmentException("'" + source + "' does not exist"); + } + moduleCompileSession.addSources(source.getPath()); } for (String classpathRoot : moduleBuilder.getClasspathRoots()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 4e7db15ef0e..1e67a337309 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -20,6 +20,7 @@ public class JetExpressionParsing extends AbstractJetParsing { private static final TokenSet WHEN_CONDITION_RECOVERY_SET = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD); private static final TokenSet WHEN_CONDITION_RECOVERY_SET_WITH_ARROW = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD, ARROW, DOT); + private static final ImmutableMap KEYWORD_TEXTS = tokenSetToMap(KEYWORDS); private static ImmutableMap tokenSetToMap(TokenSet tokens) { @@ -1406,9 +1407,9 @@ public class JetExpressionParsing extends AbstractJetParsing { parseControlStructureBody(); } - expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition"); - - parseCondition(); + if (expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition")) { + parseCondition(); + } loop.done(DO_WHILE); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java b/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java index 8464fd84c72..5d2503916d6 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ForTestCompileStdlib.java @@ -80,7 +80,7 @@ public class ForTestCompileStdlib { private static void compileKotlinPartOfStdlib(File destdir) throws IOException { // lame - KotlinCompiler.main("-output", destdir.getPath(), "-src", "./stdlib/ktSrc"); + KotlinCompiler.exec("-output", destdir.getPath(), "-src", "./stdlib/ktSrc"); } private static List javaFilesInDir(File dir) { diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java index 12869e95dad..b1054ea97a3 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java @@ -38,7 +38,7 @@ public class CompileEnvironmentTest extends TestCase { try { File stdlib = ForTestCompileStdlib.stdlibJarForTests(); File resultJar = new File(tempDir, "result.jar"); - KotlinCompiler.main("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", + KotlinCompiler.exec("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", "-jar", resultJar.getAbsolutePath(), "-stdlib", stdlib.getAbsolutePath()); FileInputStream fileInputStream = new FileInputStream(resultJar); @@ -68,7 +68,7 @@ public class CompileEnvironmentTest extends TestCase { File out = new File(tempDir, "out"); File stdlib = new File(tempDir, "stdlib.jar"); FileUtil.copy(ForTestCompileStdlib.stdlibJarForTests(), stdlib); - KotlinCompiler.main("-src", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kt", + KotlinCompiler.exec("-src", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kt", "-output", out.getAbsolutePath(), "-stdlib", stdlib.getAbsolutePath()); diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java b/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java index 2fd443a39c9..9bfa22ee50d 100644 --- a/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java +++ b/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java @@ -2,9 +2,9 @@ package org.jetbrains.jet.plugin.formatter; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.TokenType; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; @@ -16,15 +16,14 @@ import java.util.Collections; import java.util.List; /** + * @see Block for good JavaDoc documentation * @author yole */ -public class JetBlock implements ASTBlock { - private ASTNode myNode; - private Alignment myAlignment; +public class JetBlock extends AbstractBlock { private Indent myIndent; - private Wrap myWrap; private CodeStyleSettings mySettings; private final SpacingBuilder mySpacingBuilder; + private List mySubBlocks; private static final TokenSet CODE_BLOCKS = TokenSet.create( @@ -35,52 +34,35 @@ public class JetBlock implements ASTBlock { private static final TokenSet STATEMENT_PARTS = TokenSet.create( JetNodeTypes.THEN, JetNodeTypes.ELSE); + + // private static final List - public JetBlock(ASTNode node, Alignment alignment, Indent indent, Wrap wrap, CodeStyleSettings settings, - SpacingBuilder spacingBuilder) { - myNode = node; - myAlignment = alignment; + public JetBlock(@NotNull ASTNode node, + Alignment alignment, + Indent indent, + Wrap wrap, + CodeStyleSettings settings, + SpacingBuilder spacingBuilder) { + + super(node, wrap, alignment); myIndent = indent; - myWrap = wrap; mySettings = settings; mySpacingBuilder = spacingBuilder; } - @Override - public ASTNode getNode() { - return myNode; - } - - @NotNull - @Override - public TextRange getTextRange() { - return myNode.getTextRange(); - } - - @Override - public Wrap getWrap() { - return myWrap; - } - @Override public Indent getIndent() { return myIndent; } @Override - public Alignment getAlignment() { - return myAlignment; - } - - @NotNull - @Override - public List getSubBlocks() { + protected List buildChildren() { if (mySubBlocks == null) { mySubBlocks = buildSubBlocks(); } return new ArrayList(mySubBlocks); } - + private List buildSubBlocks() { List blocks = new ArrayList(); for (ASTNode child = myNode.getFirstChildNode(); child != null; child = child.getTreeNext()) { @@ -97,7 +79,8 @@ public class JetBlock implements ASTBlock { return Collections.unmodifiableList(blocks); } - private Block buildSubBlock(ASTNode child) { + @NotNull + private Block buildSubBlock(@NotNull ASTNode child) { Wrap wrap = null; Indent childIndent = Indent.getNoneIndent(); Alignment childAlignment = null; @@ -128,7 +111,7 @@ public class JetBlock implements ASTBlock { return new JetBlock(child, childAlignment, childIndent, wrap, mySettings, mySpacingBuilder); } - private static Indent indentIfNotBrace(ASTNode child) { + private static Indent indentIfNotBrace(@NotNull ASTNode child) { return child.getElementType() == JetTokens.RBRACE || child.getElementType() == JetTokens.LBRACE ? Indent.getNoneIndent() : Indent.getNormalIndent(); @@ -151,16 +134,18 @@ public class JetBlock implements ASTBlock { @NotNull @Override public ChildAttributes getChildAttributes(int newChildIndex) { - Indent childIndent = Indent.getNoneIndent(); - if (CODE_BLOCKS.contains(myNode.getElementType()) || myNode.getElementType() == JetNodeTypes.WHEN) { - childIndent = Indent.getNormalIndent(); - } - return new ChildAttributes(childIndent, null); - } + final IElementType type = getNode().getElementType(); + if (CODE_BLOCKS.contains(type) || + type == JetNodeTypes.WHEN || + type == JetNodeTypes.IF || + type == JetNodeTypes.FOR || + type == JetNodeTypes.WHILE || + type == JetNodeTypes.DO_WHILE) { - @Override - public boolean isIncomplete() { - return false; + return new ChildAttributes(Indent.getNormalIndent(), null); + } + + return new ChildAttributes(Indent.getNoneIndent(), null); } @Override diff --git a/idea/testData/formatter/IndentationOnNewline/DoInFun.after.kt b/idea/testData/formatter/IndentationOnNewline/DoInFun.after.kt new file mode 100644 index 00000000000..e168ec583e2 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/DoInFun.after.kt @@ -0,0 +1,4 @@ +fun some() { + do + +} \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/DoInFun.kt b/idea/testData/formatter/IndentationOnNewline/DoInFun.kt new file mode 100644 index 00000000000..4c17791e4e2 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/DoInFun.kt @@ -0,0 +1,3 @@ +fun some() { + do +} \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/For.after.kt b/idea/testData/formatter/IndentationOnNewline/For.after.kt new file mode 100644 index 00000000000..0fc22bb9341 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/For.after.kt @@ -0,0 +1,3 @@ +fun some() { + for (var i in 1..10) + \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/For.kt b/idea/testData/formatter/IndentationOnNewline/For.kt new file mode 100644 index 00000000000..e0306a79eb4 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/For.kt @@ -0,0 +1,2 @@ +fun some() { + for (var i in 1..10) \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/If.after.kt b/idea/testData/formatter/IndentationOnNewline/If.after.kt new file mode 100644 index 00000000000..ac818828a71 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/If.after.kt @@ -0,0 +1,4 @@ +fun some() { + if (3 > 5) + +} \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/If.kt b/idea/testData/formatter/IndentationOnNewline/If.kt new file mode 100644 index 00000000000..8f5f367e3b4 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/If.kt @@ -0,0 +1,3 @@ +fun some() { + if (3 > 5) +} \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/While.after.kt b/idea/testData/formatter/IndentationOnNewline/While.after.kt new file mode 100644 index 00000000000..568a7d9a336 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/While.after.kt @@ -0,0 +1,4 @@ +fun some() { + var t = 12 + while (t > 0) + \ No newline at end of file diff --git a/idea/testData/formatter/IndentationOnNewline/While.kt b/idea/testData/formatter/IndentationOnNewline/While.kt new file mode 100644 index 00000000000..93cb6c3c351 --- /dev/null +++ b/idea/testData/formatter/IndentationOnNewline/While.kt @@ -0,0 +1,3 @@ +fun some() { + var t = 12 + while (t > 0) \ No newline at end of file diff --git a/idea/tests/org.jetbrains.jet.formatter/AbstractKotlinFormatterTest.java b/idea/tests/org/jetbrains/jet/formatter/AbstractJetFormatterTest.java similarity index 96% rename from idea/tests/org.jetbrains.jet.formatter/AbstractKotlinFormatterTest.java rename to idea/tests/org/jetbrains/jet/formatter/AbstractJetFormatterTest.java index e4d1709d83c..0bc2dd41f47 100644 --- a/idea/tests/org.jetbrains.jet.formatter/AbstractKotlinFormatterTest.java +++ b/idea/tests/org/jetbrains/jet/formatter/AbstractJetFormatterTest.java @@ -39,7 +39,7 @@ import java.util.Map; // Based on from com.intellij.psi.formatter.java.AbstractJavaFormatterTest @SuppressWarnings("UnusedDeclaration") -public abstract class AbstractKotlinFormatterTest extends LightIdeaTestCase { +public abstract class AbstractJetFormatterTest extends LightIdeaTestCase { protected enum Action {REFORMAT, INDENT} @@ -96,6 +96,10 @@ public abstract class AbstractKotlinFormatterTest extends LightIdeaTestCase { doTextTest(Action.REFORMAT, text, textAfter); } + public void doIndentTextTest(@NonNls final String text, @NonNls String textAfter) throws IncorrectOperationException { + doTextTest(Action.INDENT, text, textAfter); + } + public void doTextTest(final Action action, final String text, String textAfter) throws IncorrectOperationException { final PsiFile file = createFile("A.kt", text); diff --git a/idea/tests/org.jetbrains.jet.formatter/KotlinFormatterTest.java b/idea/tests/org/jetbrains/jet/formatter/JetFormatterTest.java similarity index 88% rename from idea/tests/org.jetbrains.jet.formatter/KotlinFormatterTest.java rename to idea/tests/org/jetbrains/jet/formatter/JetFormatterTest.java index 0230cda7c12..5f6ca551d5d 100644 --- a/idea/tests/org.jetbrains.jet.formatter/KotlinFormatterTest.java +++ b/idea/tests/org/jetbrains/jet/formatter/JetFormatterTest.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.formatter; /** * Based on com.intellij.psi.formatter.java.JavaFormatterTest */ -public class KotlinFormatterTest extends AbstractKotlinFormatterTest { +public class JetFormatterTest extends AbstractJetFormatterTest { public void testBlockFor() throws Exception { doTest(); } diff --git a/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTest.java b/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTest.java new file mode 100644 index 00000000000..524c6d60f0a --- /dev/null +++ b/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTest.java @@ -0,0 +1,40 @@ +package org.jetbrains.jet.formatter; + +import com.intellij.testFramework.LightCodeInsightTestCase; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +import java.io.File; + +/** + * @author Nikolay Krasko + */ +public class JetTypingIndentationTest extends LightCodeInsightTestCase { + public void testWhile() { + doFileNewlineTest(); + } + + public void testFor() { + doFileNewlineTest(); + } + + public void testIf() { + doFileNewlineTest(); + } + + public void testDoInFun() { + doFileNewlineTest(); + } + + public void doFileNewlineTest() { + configureByFile(getTestName(false) + ".kt"); + type('\n'); + checkResultByFile(getTestName(false) + ".after.kt"); + } + + @Override + protected String getTestDataPath() { + final String testRelativeDir = "formatter/IndentationOnNewline"; + return new File(PluginTestCaseBase.getTestDataPathBase(), testRelativeDir).getPath() + + File.separator; + } +} diff --git a/testlib/test/StdLibIssuesTest.kt b/testlib/test/StdLibIssuesTest.kt new file mode 100644 index 00000000000..f8e6856a354 --- /dev/null +++ b/testlib/test/StdLibIssuesTest.kt @@ -0,0 +1,24 @@ +package test.stdlib.issues + +import java.util.List +import std.util.* +import stdhack.test.* + +private fun listDifference(first : List, second : List) : List { + return first.filter{ !second.contains(it) }.toList() +} + +class StdLibIssuesTest() : TestSupport() { + + fun test_KT_1131() { + val data = arrayList("blah", "foo", "bar") + val filterValues = arrayList("bar", "something", "blah") + + expect(arrayList("foo")) { + val answer = listDifference(data, filterValues) + println("Found answer ${answer}") + answer + } + } + +}