KT-12877: initial simple implementation of JsModule. Remove unnecessary ModuleDescriptor from several classes in pipeline

This commit is contained in:
Alexey Andreev
2016-06-28 14:40:49 +03:00
committed by Alexey Andreev
parent 75d80acac9
commit 6df40559f0
14 changed files with 167 additions and 12 deletions
@@ -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();
}
}
+4
View File
@@ -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;
});