diff --git a/annotations/com/intellij/psi/annotations.xml b/annotations/com/intellij/psi/annotations.xml index b024c06da0b..5b4da145766 100644 --- a/annotations/com/intellij/psi/annotations.xml +++ b/annotations/com/intellij/psi/annotations.xml @@ -304,6 +304,9 @@ + + + diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java index 9cd5d4fd696..928a3ce4e45 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java @@ -144,23 +144,23 @@ public class JetPsiFactory { } @NotNull - public static JetClass createClass(Project project, String text) { + public static JetClass createClass(@NotNull Project project, @NotNull String text) { return createDeclaration(project, text, JetClass.class); } @NotNull - public static JetFile createFile(Project project, String text) { + public static JetFile createFile(@NotNull Project project, @NotNull String text) { return createFile(project, "dummy.kt", text); } @NotNull - public static JetFile createFile(Project project, String fileName, String text) { + public static JetFile createFile(@NotNull Project project, @NotNull String fileName, @NotNull String text) { return (JetFile) PsiFileFactory.getInstance(project).createFileFromText(fileName, JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), false); } @NotNull - public static JetFile createPhysicalFile(Project project, String fileName, String text) { + public static JetFile createPhysicalFile(@NotNull Project project, @NotNull String fileName, @NotNull String text) { return (JetFile) PsiFileFactory.getInstance(project).createFileFromText(fileName, JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true); } diff --git a/j2k/src/org/jetbrains/jet/j2k/AfterConversionPass.kt b/j2k/src/org/jetbrains/jet/j2k/AfterConversionPass.kt new file mode 100644 index 00000000000..452892ad535 --- /dev/null +++ b/j2k/src/org/jetbrains/jet/j2k/AfterConversionPass.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.j2k + +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM +import org.jetbrains.jet.lang.resolve.BindingTraceContext +import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.jet.lang.resolve.name.Name +import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap +import com.intellij.openapi.project.Project +import org.jetbrains.jet.lang.diagnostics.Diagnostic +import org.jetbrains.jet.lang.diagnostics.Errors +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression +import org.jetbrains.jet.lang.psi.JetUnaryExpression + +class AfterConversionPass(val project: Project) { + public fun run(kotlinCode: String): String { + val kotlinFile = JetPsiFactory.createFile(project, kotlinCode) + val analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( + project, + listOf(kotlinFile), + BindingTraceContext(), + { true }, + ModuleDescriptorImpl(Name.special(""), AnalyzerFacadeForJVM.DEFAULT_IMPORTS, JavaToKotlinClassMap.getInstance()), + null, + null + ) + + val problems = analyzeExhaust.getBindingContext().getDiagnostics() + val fixes = problems.map { + val fix = fixForProblem(it) + if (fix != null) it.getPsiElement() to fix else null + }.filterNotNull() + + if (fixes.isEmpty()) return kotlinCode + + for ((psiElement, fix) in fixes) { + if (psiElement.isValid()) { + fix() + } + } + return kotlinFile.getText()!! + } + + private fun fixForProblem(problem: Diagnostic): (() -> Unit)? { + return when (problem.getFactory()) { + Errors.UNNECESSARY_NOT_NULL_ASSERTION -> { () -> + val exclExclOp = problem.getPsiElement() as JetSimpleNameExpression + val exclExclExpr = exclExclOp.getParent() as JetUnaryExpression + exclExclExpr.replace(exclExclExpr.getBaseExpression()!!) + } + + else -> null + } + } +} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index d9e3a632c77..02f35dfdd83 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -61,7 +61,7 @@ public class Converter private(val project: Project, val settings: ConverterSett val converted = convertTopElement(element) ?: return "" val builder = CodeBuilder(element) builder.append(converted) - return builder.result + return AfterConversionPass(project).run(builder.result) } private fun convertTopElement(element: PsiElement?): Element? = when (element) { @@ -78,7 +78,7 @@ public class Converter private(val project: Project, val settings: ConverterSett else -> null } - fun convertFile(javaFile: PsiJavaFile): File { + private fun convertFile(javaFile: PsiJavaFile): File { var convertedChildren = javaFile.getChildren().map { if (it is PsiImportList) { val importList = convertImportList(it) diff --git a/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt b/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt index 8c97cd0e710..c1b7cb7b2b6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt +++ b/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt @@ -21,21 +21,19 @@ import com.intellij.core.JavaCoreProjectEnvironment import com.intellij.lang.java.JavaLanguage import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer -import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiFileFactory import com.intellij.psi.PsiJavaFile import org.jetbrains.jet.utils.PathUtil import java.io.File import java.net.URLClassLoader -import java.util.HashSet public object JavaToKotlinTranslator { private val DISPOSABLE = Disposer.newDisposable() private fun createFile(text: String): PsiFile? { val javaCoreEnvironment: JavaCoreProjectEnvironment? = setUpJavaCoreEnvironment() - return PsiFileFactory.getInstance(javaCoreEnvironment?.getProject())?.createFileFromText("test.java", JavaLanguage.INSTANCE, text) + return PsiFileFactory.getInstance(javaCoreEnvironment?.getProject()!!)?.createFileFromText("test.java", JavaLanguage.INSTANCE, text) } fun createFile(project: Project, text: String): PsiJavaFile { diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java index 40a5375571d..3bc6b7ea6e2 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -2199,6 +2199,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/nullability"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("autoNotNull.java") + public void testAutoNotNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/autoNotNull.java"); + } + @TestMetadata("FieldAssignedWithNull.java") public void testFieldAssignedWithNull() throws Exception { doTest("j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java"); diff --git a/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt b/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt index 95eb63cf760..36d5b9672a2 100644 --- a/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt +++ b/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt @@ -10,7 +10,7 @@ public class Test(str: String) { } public fun sout(str: String) { - System.out!!.println(str) + System.out.println(str) } public fun dummy(str: String): String { diff --git a/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt b/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt index 1bfbd71d7ee..9b4ceebf396 100644 --- a/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt +++ b/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt @@ -17,6 +17,6 @@ class Test { barNotNull.fooNotNull.execute() barNotNull.fooNullable!!.execute() barNullable!!.fooNotNull.execute() - barNullable!!.fooNullable!!.execute() + barNullable.fooNullable!!.execute() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/issues/kt-824-isDir.kt b/j2k/tests/testData/ast/issues/kt-824-isDir.kt index d7dfee5cea5..2239e074545 100644 --- a/j2k/tests/testData/ast/issues/kt-824-isDir.kt +++ b/j2k/tests/testData/ast/issues/kt-824-isDir.kt @@ -8,11 +8,11 @@ import java.io.File public class Test { class object { public fun isDir(parent: File?): Boolean { - if (parent == null || !parent!!.exists()) { + if (parent == null || !parent.exists()) { return false } val result = true - if (parent!!.isDirectory()) { + if (parent.isDirectory()) { return true } else return false diff --git a/j2k/tests/testData/ast/nullability/autoNotNull.java b/j2k/tests/testData/ast/nullability/autoNotNull.java new file mode 100644 index 00000000000..bf4ed4a8699 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/autoNotNull.java @@ -0,0 +1,9 @@ +//file +class A { + int foo(String s) { + if (s != null) { + return s.length(); + } + return -1; + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/autoNotNull.kt b/j2k/tests/testData/ast/nullability/autoNotNull.kt new file mode 100644 index 00000000000..ae7a34d9237 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/autoNotNull.kt @@ -0,0 +1,8 @@ +class A { + fun foo(s: String?): Int { + if (s != null) { + return s.length() + } + return -1 + } +} \ No newline at end of file