Use kotlin.Lazy for script definition computation, add test for no definition

This commit is contained in:
Alexander Udalov
2017-06-21 18:50:17 +03:00
parent 4178188e15
commit 1f34dfabd5
2 changed files with 32 additions and 15 deletions
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import kotlin.Lazy;
import kotlin.LazyKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.stubs.KotlinScriptStub; import org.jetbrains.kotlin.psi.stubs.KotlinScriptStub;
@@ -26,21 +28,15 @@ import org.jetbrains.kotlin.script.KotlinScriptDefinition;
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProviderKt; import org.jetbrains.kotlin.script.KotlinScriptDefinitionProviderKt;
import java.util.List; import java.util.List;
import java.util.Objects;
import static kotlin.LazyThreadSafetyMode.PUBLICATION;
public class KtScript extends KtNamedDeclarationStub<KotlinScriptStub> implements KtDeclarationContainer { public class KtScript extends KtNamedDeclarationStub<KotlinScriptStub> implements KtDeclarationContainer {
private final Lazy<KotlinScriptDefinition> kotlinScriptDefinition = LazyKt.lazy(PUBLICATION, () -> Objects.requireNonNull(
private KotlinScriptDefinition kotlinScriptDefinitionField = null; KotlinScriptDefinitionProviderKt.getScriptDefinition(getContainingKtFile()),
private boolean kotlinScriptDefinitionInitialized = false; () -> "Should not parse a script without definition: " + getContainingKtFile().getVirtualFile().getPath()
));
// make it a simple lazy value after converting to kotlin
private KotlinScriptDefinition getKotlinScriptDefinition() {
if (!kotlinScriptDefinitionInitialized) {
kotlinScriptDefinitionField = KotlinScriptDefinitionProviderKt.getScriptDefinition(getContainingKtFile());
kotlinScriptDefinitionInitialized = true;
}
assert kotlinScriptDefinitionField != null : "Should not parse a script without definition: " + getContainingKtFile().toString();
return kotlinScriptDefinitionField;
}
public KtScript(@NotNull ASTNode node) { public KtScript(@NotNull ASTNode node) {
super(node); super(node);
@@ -58,7 +54,7 @@ public class KtScript extends KtNamedDeclarationStub<KotlinScriptStub> implement
return stub.getFqName(); return stub.getFqName();
} }
KtFile containingKtFile = getContainingKtFile(); KtFile containingKtFile = getContainingKtFile();
return containingKtFile.getPackageFqName().child(getKotlinScriptDefinition().getScriptName(this)); return containingKtFile.getPackageFqName().child(kotlinScriptDefinition.getValue().getScriptName(this));
} }
@Override @Override
@@ -67,7 +63,7 @@ public class KtScript extends KtNamedDeclarationStub<KotlinScriptStub> implement
} }
@NotNull @NotNull
public KtBlockExpression getBlockExpression() { private KtBlockExpression getBlockExpression() {
return findNotNullChildByClass(KtBlockExpression.class); return findNotNullChildByClass(KtBlockExpression.class);
} }
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.script.*
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.util.KotlinFrontEndException
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
@@ -251,6 +252,20 @@ class ScriptTemplateTest {
Assert.assertTrue(exceptionThrown) Assert.assertTrue(exceptionThrown)
} }
@Test
fun testScriptWithNoMatchingTemplate() {
try {
compileScript("fib.kts", ScriptWithDifferentFileNamePattern::class, null)
Assert.fail("should throw compilation error")
}
catch (e: KotlinFrontEndException) {
if (e.message?.contains("Should not parse a script without definition") != true) {
// unexpected error
throw e
}
}
}
private fun compileScript( private fun compileScript(
scriptPath: String, scriptPath: String,
scriptTemplate: KClass<out Any>, scriptTemplate: KClass<out Any>,
@@ -387,6 +402,12 @@ abstract class ScriptWithoutParams(num: Int)
resolver = TestKotlinScriptDependenciesResolver::class) resolver = TestKotlinScriptDependenciesResolver::class)
abstract class ScriptBaseClassWithOverriddenProperty(override val num: Int) : TestClassWithOverridableProperty(num) abstract class ScriptBaseClassWithOverriddenProperty(override val num: Int) : TestClassWithOverridableProperty(num)
@ScriptTemplateDefinition(
scriptFilePattern = ".*\\.custom\\.kts",
resolver = TestKotlinScriptDependenciesResolver::class
)
abstract class ScriptWithDifferentFileNamePattern
@ScriptTemplateDefinition(resolver = TestKotlinScriptDependenciesResolver::class) @ScriptTemplateDefinition(resolver = TestKotlinScriptDependenciesResolver::class)
abstract class ScriptWithArrayParam(val myArgs: Array<String>) abstract class ScriptWithArrayParam(val myArgs: Array<String>)