KT-12877: initial simple implementation of JsModule. Remove unnecessary ModuleDescriptor from several classes in pipeline
This commit is contained in:
committed by
Alexey Andreev
parent
75d80acac9
commit
6df40559f0
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
|
||||
public final class AnnotationsUtils {
|
||||
private static final String JS_NAME = "kotlin.js.JsName";
|
||||
private static final FqName JS_MODULE_ANNOTATION = new FqName("kotlin.js.JsModule");
|
||||
|
||||
private AnnotationsUtils() {
|
||||
}
|
||||
@@ -169,4 +170,14 @@ public final class AnnotationsUtils {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getModuleName(@NotNull DeclarationDescriptor declaration) {
|
||||
AnnotationDescriptor annotation = declaration.getAnnotations().findAnnotation(JS_MODULE_ANNOTATION);
|
||||
if (annotation == null) return null;
|
||||
|
||||
ConstantValue<?> importValue = annotation.getAllValueArguments().values().iterator().next();
|
||||
assert importValue != null : "JsModule annotation should have at least one argument";
|
||||
return (String) importValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,3 +49,7 @@ internal annotation class marker
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
annotation class JsName(val name: String)
|
||||
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(CLASS, PROPERTY, FUNCTION, FILE)
|
||||
annotation class JsModule(val import: String)
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.kotlin.js.test.semantics;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("js/js.translator/testData/jsModule/cases")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class JsModuleTestGenerated extends AbstractJsModuleTest {
|
||||
public void testAllFilesPresentInCases() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/jsModule/cases"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("externalClass.kt")
|
||||
public void testExternalClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/jsModule/cases/externalClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("externalFunction.kt")
|
||||
public void testExternalFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/jsModule/cases/externalFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("externalObject.kt")
|
||||
public void testExternalObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/jsModule/cases/externalObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("externalProperty.kt")
|
||||
public void testExternalProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/jsModule/cases/externalProperty.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ public final class K2JSTranslator {
|
||||
ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
|
||||
Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
|
||||
|
||||
TranslationContext context = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
|
||||
TranslationContext context = Translation.generateAst(bindingTrace, files, mainCallParameters, config);
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.js.translate.context.generator.Generator;
|
||||
import org.jetbrains.kotlin.js.translate.context.generator.Rule;
|
||||
import org.jetbrains.kotlin.js.translate.declaration.InterfaceFunctionCopier;
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
@@ -395,6 +396,9 @@ public final class StaticContext {
|
||||
return config;
|
||||
}
|
||||
|
||||
// TODO: add this to NameSuggestion:
|
||||
// String moduleName = AnnotationsUtils.getModuleName(descriptor);
|
||||
|
||||
@NotNull
|
||||
public JsName importDeclaration(@NotNull String suggestedName, @NotNull JsExpression declaration) {
|
||||
// Adding prefix is a workaround for a problem with scopes.
|
||||
@@ -595,13 +599,22 @@ public final class StaticContext {
|
||||
|
||||
if (UNKNOWN_EXTERNAL_MODULE_NAME.equals(moduleName)) return null;
|
||||
|
||||
JsName moduleId = moduleName.equals(Namer.KOTLIN_LOWER_NAME) ? rootScope.declareName(Namer.KOTLIN_NAME) :
|
||||
importedModules.get(moduleName);
|
||||
if (moduleId == null) {
|
||||
moduleId = rootScope.declareFreshName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(moduleName));
|
||||
importedModules.put(moduleName, moduleId);
|
||||
}
|
||||
return getModuleReference(moduleName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsNameRef getModuleReference(@NotNull String baseName) {
|
||||
return JsAstUtils.pureFqn(getModuleInternalName(baseName), null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsName getModuleInternalName(@NotNull String baseName) {
|
||||
JsName moduleId = baseName.equals(Namer.KOTLIN_LOWER_NAME) ? rootScope.declareName(Namer.KOTLIN_NAME) :
|
||||
importedModules.get(baseName);
|
||||
if (moduleId == null) {
|
||||
moduleId = rootScope.declareFreshName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName));
|
||||
importedModules.put(baseName, moduleId);
|
||||
}
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
@@ -229,11 +228,10 @@ public final class Translation {
|
||||
@NotNull BindingTrace bindingTrace,
|
||||
@NotNull Collection<KtFile> files,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull ModuleDescriptor moduleDescriptor,
|
||||
@NotNull JsConfig config
|
||||
) throws TranslationException {
|
||||
try {
|
||||
return doGenerateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
|
||||
return doGenerateAst(bindingTrace, files, mainCallParameters, config);
|
||||
}
|
||||
catch (UnsupportedOperationException e) {
|
||||
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
||||
@@ -248,10 +246,9 @@ public final class Translation {
|
||||
@NotNull BindingTrace bindingTrace,
|
||||
@NotNull Collection<KtFile> files,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull ModuleDescriptor moduleDescriptor,
|
||||
@NotNull JsConfig config
|
||||
) {
|
||||
StaticContext staticContext = StaticContext.generateStaticContext(bindingTrace, config, moduleDescriptor);
|
||||
StaticContext staticContext = StaticContext.generateStaticContext(bindingTrace, config);
|
||||
JsProgram program = staticContext.getProgram();
|
||||
JsName rootPackageName = program.getRootScope().declareName(Namer.getRootPackageName());
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package foo
|
||||
|
||||
@JsModule("lib") @native class A(@native val x: Int = noImpl) {
|
||||
@native fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A(23)
|
||||
assertEquals(23, a.x)
|
||||
assertEquals(65, a.foo(42))
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package foo
|
||||
|
||||
@JsModule("lib") @native fun foo(y: Int): Int = noImpl
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(65, foo(42))
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package foo
|
||||
|
||||
@JsModule("lib") @native object A {
|
||||
@native val x: Int = noImpl
|
||||
|
||||
@native fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(23, A.x)
|
||||
assertEquals(65, A.foo(42))
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package foo
|
||||
|
||||
@JsModule("lib") @native val foo: Int = noImpl
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(23, foo)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
define("lib", [], function() {
|
||||
function A(x) {
|
||||
this.x = x;
|
||||
}
|
||||
A.prototype.foo = function (y) {
|
||||
return this.x + y;
|
||||
};
|
||||
|
||||
return A;
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
define("lib", [], function() {
|
||||
return function(y) {
|
||||
return 23 + y;
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
define("lib", [], function() {
|
||||
A = {
|
||||
x: 23,
|
||||
foo: function(y) {
|
||||
return this.x + y;
|
||||
}
|
||||
};
|
||||
|
||||
return A;
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
define("lib", [], function() {
|
||||
return 23;
|
||||
});
|
||||
Reference in New Issue
Block a user