JS: support inlining in new pipeline
This commit is contained in:
@@ -17,10 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.callUtil
|
||||
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -210,6 +207,15 @@ fun KtExpression.getPropertyResolvedCallWithAssert(context: BindingContext): Res
|
||||
return resolvedCall as ResolvedCall<out PropertyDescriptor>
|
||||
}
|
||||
|
||||
fun KtExpression.getVariableResolvedCallWithAssert(context: BindingContext): ResolvedCall<out VariableDescriptor> {
|
||||
val resolvedCall = getResolvedCallWithAssert(context)
|
||||
assert(resolvedCall.resultingDescriptor is VariableDescriptor) {
|
||||
"ResolvedCall for this expression must be ResolvedCall<? extends PropertyDescriptor>: ${this.getTextWithLocation()}"
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return resolvedCall as ResolvedCall<out VariableDescriptor>
|
||||
}
|
||||
|
||||
fun KtExpression.getType(context: BindingContext): KotlinType? {
|
||||
val type = context.getType(this)
|
||||
if (type != null) return type
|
||||
|
||||
@@ -17,6 +17,7 @@ public class JsProgramFragment {
|
||||
private final JsGlobalBlock initializerBlock = new JsGlobalBlock();
|
||||
private final List<JsNameBinding> nameBindings = new ArrayList<JsNameBinding>();
|
||||
private final Map<JsName, JsClassModel> classes = new LinkedHashMap<JsName, JsClassModel>();
|
||||
private final Map<String, JsExpression> inlineModuleMap = new LinkedHashMap<String, JsExpression>();
|
||||
|
||||
public JsProgramFragment(@NotNull JsScope scope) {
|
||||
this.scope = scope;
|
||||
@@ -61,4 +62,9 @@ public class JsProgramFragment {
|
||||
public Map<JsName, JsClassModel> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<String, JsExpression> getInlineModuleMap() {
|
||||
return inlineModuleMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,7 @@ import org.jetbrains.kotlin.js.inline.util.IdentitySet
|
||||
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
|
||||
import org.jetbrains.kotlin.js.parser.parseFunction
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
||||
@@ -48,7 +46,7 @@ private val JS_IDENTIFIER="[$JS_IDENTIFIER_START][$JS_IDENTIFIER_PART]*"
|
||||
private val DEFINE_MODULE_PATTERN = ("($JS_IDENTIFIER)\\.defineModule\\(\\s*(['\"])([^'\"]+)\\2\\s*,\\s*(\\w+)\\s*\\)").toRegex().toPattern()
|
||||
private val DEFINE_MODULE_FIND_PATTERN = ".defineModule("
|
||||
|
||||
class FunctionReader(private val context: TranslationContext) {
|
||||
class FunctionReader(private val config: LibrarySourcesConfig, private val currentModuleName: JsName, fragments: List<JsProgramFragment>) {
|
||||
/**
|
||||
* fileContent: .js file content, that contains this module definition.
|
||||
* One file can contain more than one module definition.
|
||||
@@ -63,8 +61,12 @@ class FunctionReader(private val context: TranslationContext) {
|
||||
|
||||
private val moduleNameToInfo = HashMultimap.create<String, ModuleInfo>()
|
||||
|
||||
private val moduleNameMap: Map<String, JsExpression>
|
||||
|
||||
init {
|
||||
val libs = context.config.libraries.map(::File)
|
||||
val libs = config.libraries.map(::File)
|
||||
|
||||
moduleNameMap = buildModuleNameMap(fragments)
|
||||
|
||||
JsLibraryUtils.traverseJsLibraries(libs) { fileContent, _ ->
|
||||
var current = 0
|
||||
@@ -86,6 +88,13 @@ class FunctionReader(private val context: TranslationContext) {
|
||||
}
|
||||
}
|
||||
|
||||
// Since we compile each source file in its own context (and we may loose these context when performing incremental compilation)
|
||||
// we don't use contexts to generate proper names for modules. Instead, we generate all necessary information during
|
||||
// translation and rely on it here.
|
||||
private fun buildModuleNameMap(fragments: List<JsProgramFragment>): Map<String, JsExpression> {
|
||||
return fragments.flatMap { it.inlineModuleMap.entries }.associate { (k, v) -> k to v }
|
||||
}
|
||||
|
||||
private fun rewindToIdentifierStart(text: String, index: Int): Int {
|
||||
var result = index
|
||||
while (result > 0 && Character.isJavaIdentifierPart(text[result - 1])) {
|
||||
@@ -112,7 +121,7 @@ class FunctionReader(private val context: TranslationContext) {
|
||||
|
||||
operator fun contains(descriptor: CallableDescriptor): Boolean {
|
||||
val moduleName = getModuleName(descriptor)
|
||||
val currentModuleName = context.config.moduleId
|
||||
val currentModuleName = config.moduleId
|
||||
return currentModuleName != moduleName && moduleName in moduleNameToInfo.keys()
|
||||
}
|
||||
|
||||
@@ -144,7 +153,7 @@ class FunctionReader(private val context: TranslationContext) {
|
||||
}
|
||||
|
||||
val function = parseFunction(source, offset, ThrowExceptionOnErrorReporter, JsRootScope(JsProgram()))
|
||||
val moduleReference = context.getModuleExpressionFor(descriptor) ?: getRootPackage()
|
||||
val moduleReference = moduleNameMap[tag] ?: currentModuleName.makeRef()
|
||||
|
||||
val replacements = hashMapOf(info.moduleVariable to moduleReference,
|
||||
info.kotlinVariable to Namer.kotlinObject())
|
||||
@@ -152,11 +161,6 @@ class FunctionReader(private val context: TranslationContext) {
|
||||
function.markInlineArguments(descriptor)
|
||||
return function
|
||||
}
|
||||
|
||||
private fun getRootPackage(): JsExpression {
|
||||
val rootName = context.program().rootScope.declareName(Namer.getRootPackageName())
|
||||
return JsAstUtils.pureFqn(rootName, null)
|
||||
}
|
||||
}
|
||||
|
||||
private val Char.isWhitespaceOrComma: Boolean
|
||||
|
||||
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig;
|
||||
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor;
|
||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedFunctionDefinitionsKt;
|
||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedLocalFunctionDeclarationsKt;
|
||||
@@ -37,7 +39,6 @@ import org.jetbrains.kotlin.js.inline.context.NamingContext;
|
||||
import org.jetbrains.kotlin.js.inline.util.CollectUtilsKt;
|
||||
import org.jetbrains.kotlin.js.inline.util.CollectionUtilsKt;
|
||||
import org.jetbrains.kotlin.js.inline.util.NamingUtilsKt;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy;
|
||||
|
||||
import java.util.*;
|
||||
@@ -61,15 +62,34 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
private final Function1<JsNode, Boolean> canBeExtractedByInliner =
|
||||
node -> node instanceof JsInvocation && hasToBeInlined((JsInvocation) node);
|
||||
|
||||
public static JsProgram process(@NotNull TranslationContext context) {
|
||||
JsProgram program = context.program();
|
||||
Map<JsName, JsFunction> functions = CollectUtilsKt.collectNamedFunctions(program);
|
||||
Map<String, JsFunction> accessors = CollectUtilsKt.collectAccessors(program);
|
||||
new DummyAccessorInvocationTransformer().accept(program);
|
||||
JsInliner inliner = new JsInliner(functions, accessors, new FunctionReader(context), context.bindingTrace());
|
||||
inliner.accept(program);
|
||||
RemoveUnusedFunctionDefinitionsKt.removeUnusedFunctionDefinitions(program, functions);
|
||||
return program;
|
||||
public static void process(
|
||||
@NotNull JsConfig config,
|
||||
@NotNull DiagnosticSink trace,
|
||||
@NotNull JsName currentModuleName,
|
||||
@NotNull List<JsProgramFragment> fragments,
|
||||
@NotNull List<JsProgramFragment> fragmentsToProcess
|
||||
) {
|
||||
Map<JsName, JsFunction> functions = CollectUtilsKt.collectNamedFunctions(fragments);
|
||||
Map<String, JsFunction> accessors = CollectUtilsKt.collectAccessors(fragments);
|
||||
DummyAccessorInvocationTransformer accessorInvocationTransformer = new DummyAccessorInvocationTransformer();
|
||||
for (JsProgramFragment fragment : fragmentsToProcess) {
|
||||
accessorInvocationTransformer.accept(fragment.getDeclarationBlock());
|
||||
accessorInvocationTransformer.accept(fragment.getInitializerBlock());
|
||||
}
|
||||
FunctionReader functionReader = new FunctionReader((LibrarySourcesConfig) config, currentModuleName, fragments);
|
||||
JsInliner inliner = new JsInliner(functions, accessors, functionReader, trace);
|
||||
for (JsProgramFragment fragment : fragmentsToProcess) {
|
||||
inliner.inliningContexts.push(inliner.new JsInliningContext(null, fragment.getScope()));
|
||||
inliner.accept(fragment.getDeclarationBlock());
|
||||
|
||||
// There can be inlined function in top-level initializers, we need to optimize them as well
|
||||
JsFunction fakeInitFunction = new JsFunction(JsDynamicScope.INSTANCE, fragment.getInitializerBlock(), "");
|
||||
inliner.accept(fakeInitFunction);
|
||||
|
||||
inliner.inliningContexts.pop();
|
||||
JsBlock block = new JsBlock(fragment.getDeclarationBlock(), fragment.getInitializerBlock(), fragment.getExportBlock());
|
||||
RemoveUnusedFunctionDefinitionsKt.removeUnusedFunctionDefinitions(block, functions);
|
||||
}
|
||||
}
|
||||
|
||||
private JsInliner(
|
||||
@@ -86,7 +106,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
|
||||
@Override
|
||||
public boolean visit(@NotNull JsFunction function, @NotNull JsContext context) {
|
||||
inliningContexts.push(new JsInliningContext(function));
|
||||
inliningContexts.push(new JsInliningContext(function, function.getScope()));
|
||||
assert !inProcessFunctions.contains(function): "Inliner has revisited function";
|
||||
inProcessFunctions.add(function);
|
||||
|
||||
@@ -266,8 +286,8 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
private class JsInliningContext implements InliningContext {
|
||||
private final FunctionContext functionContext;
|
||||
|
||||
JsInliningContext(@NotNull JsFunction function) {
|
||||
functionContext = new FunctionContext(function, functionReader) {
|
||||
JsInliningContext(@NotNull JsScope scope) {
|
||||
functionContext = new FunctionContext(scope) {
|
||||
@Nullable
|
||||
@Override
|
||||
protected JsFunction lookUpStaticFunction(@Nullable JsName functionName) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.js.inline.util.*
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
|
||||
abstract class FunctionContext(
|
||||
private val function: JsFunction,
|
||||
private val scope: JsScope,
|
||||
private val functionReader: FunctionReader
|
||||
) {
|
||||
protected abstract fun lookUpStaticFunction(functionName: JsName?): JsFunction?
|
||||
@@ -40,7 +40,7 @@ abstract class FunctionContext(
|
||||
}
|
||||
|
||||
fun getScope(): JsScope {
|
||||
return function.scope
|
||||
return scope
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -137,6 +137,15 @@ fun collectNamedFunctions(scope: JsNode) = collectNamedFunctionsAndMetadata(scop
|
||||
|
||||
fun collectNamedFunctionsOrMetadata(scope: JsNode) = collectNamedFunctionsAndMetadata(scope).mapValues { it.value.second }
|
||||
|
||||
fun collectNamedFunctions(fragments: List<JsProgramFragment>): Map<JsName, JsFunction> {
|
||||
val result = mutableMapOf<JsName, JsFunction>()
|
||||
for (fragment in fragments) {
|
||||
result += collectNamedFunctions(fragment.declarationBlock)
|
||||
result += collectNamedFunctions(fragment.initializerBlock)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun collectNamedFunctionsAndMetadata(scope: JsNode): Map<JsName, Pair<JsFunction, JsExpression>> {
|
||||
val namedFunctions = mutableMapOf<JsName, Pair<JsFunction, JsExpression>>()
|
||||
|
||||
@@ -200,6 +209,14 @@ fun collectAccessors(scope: JsNode): Map<String, JsFunction> {
|
||||
return accessors
|
||||
}
|
||||
|
||||
fun collectAccessors(fragments: List<JsProgramFragment>): Map<String, JsFunction> {
|
||||
val result = mutableMapOf<String, JsFunction>()
|
||||
for (fragment in fragments) {
|
||||
result += collectAccessors(fragment.declarationBlock)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun <T : JsNode> collectInstances(klass: Class<T>, scope: JsNode): List<T> {
|
||||
return with(InstanceCollector(klass, visitNestedDeclarations = false)) {
|
||||
accept(scope)
|
||||
|
||||
@@ -21,12 +21,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
|
||||
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsImportedModule;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer;
|
||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
||||
import org.jetbrains.kotlin.js.inline.JsInliner;
|
||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
||||
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
||||
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult;
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
@@ -74,18 +76,20 @@ public final class K2JSTranslator {
|
||||
ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
|
||||
Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
|
||||
|
||||
JsProgram program = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
|
||||
AstGenerationResult translationResult = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||
|
||||
//JsInliner.process(program);
|
||||
ResolveTemporaryNamesKt.resolveTemporaryNames(program);
|
||||
JsInliner.process(config, analysisResult.getBindingTrace(), translationResult.getInnerModuleName(),
|
||||
translationResult.getFragments(), translationResult.getFragments());
|
||||
|
||||
ResolveTemporaryNamesKt.resolveTemporaryNames(translationResult.getProgram());
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||
|
||||
CoroutineTransformer coroutineTransformer = new CoroutineTransformer(program);
|
||||
coroutineTransformer.accept(program);
|
||||
RemoveUnusedImportsKt.removeUnusedImports(program);
|
||||
CoroutineTransformer coroutineTransformer = new CoroutineTransformer(translationResult.getProgram());
|
||||
coroutineTransformer.accept(translationResult.getProgram());
|
||||
RemoveUnusedImportsKt.removeUnusedImports(translationResult.getProgram());
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||
|
||||
@@ -93,10 +97,10 @@ public final class K2JSTranslator {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
|
||||
List<String> importedModules = new ArrayList<>();
|
||||
/*for (JsImportedModule module : context.getImportedModules()) {
|
||||
for (JsImportedModule module : translationResult.getImportedModuleList()) {
|
||||
importedModules.add(module.getExternalName());
|
||||
}*/
|
||||
return new TranslationResult.Success(config, files, program, diagnostics, importedModules, moduleDescriptor,
|
||||
bindingTrace.getBindingContext());
|
||||
}
|
||||
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
||||
moduleDescriptor, bindingTrace.getBindingContext());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@ internal class DeclarationExporter(val context: StaticContext) {
|
||||
private val objectLikeKinds = setOf(ClassKind.OBJECT, ClassKind.ENUM_ENTRY)
|
||||
private val exportedDeclarations = mutableSetOf<MemberDescriptor>()
|
||||
private val localPackageNames = mutableMapOf<FqName, JsName>()
|
||||
val statements = mutableListOf<JsStatement>()
|
||||
private val statements: MutableList<JsStatement>
|
||||
get() = context.fragment.exportBlock.statements
|
||||
|
||||
fun export(descriptor: MemberDescriptor, force: Boolean) {
|
||||
if (exportedDeclarations.contains(descriptor)) return
|
||||
|
||||
@@ -642,7 +642,7 @@ public final class StaticContext {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
||||
private JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
||||
JsName name = getModuleInnerName(descriptor);
|
||||
return name != null ? JsAstUtils.pureFqn(name, null) : null;
|
||||
}
|
||||
@@ -748,6 +748,11 @@ public final class StaticContext {
|
||||
return currentModule;
|
||||
}
|
||||
|
||||
public void addInlineCall(@NotNull CallableDescriptor descriptor) {
|
||||
String tag = Namer.getFunctionTag(descriptor);
|
||||
fragment.getInlineModuleMap().put(tag, getModuleExpressionFor(descriptor));
|
||||
}
|
||||
|
||||
/*public void postProcess() {
|
||||
addInterfaceDefaultMethods();
|
||||
rootFunction.getBody().getStatements().addAll(importStatements);
|
||||
|
||||
+2
-3
@@ -625,9 +625,8 @@ public class TranslationContext {
|
||||
callSites.add(new DeferredCallSite(constructor, invocationArgs, this));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
||||
return staticContext.getModuleExpressionFor(descriptor);
|
||||
public void addInlineCall(@NotNull CallableDescriptor descriptor) {
|
||||
staticContext.addInlineCall(descriptor);
|
||||
}
|
||||
|
||||
public void addDeclarationStatement(@NotNull JsStatement statement) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.translate.general
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsImportedModule
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsProgramFragment
|
||||
|
||||
class AstGenerationResult(
|
||||
val program: JsProgram,
|
||||
val innerModuleName: JsName,
|
||||
val fragments: List<JsProgramFragment>,
|
||||
val importedModuleList: List<JsImportedModule>
|
||||
)
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.general
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
|
||||
class Merger(private val rootFunction: JsFunction, val internalModuleName: JsName) {
|
||||
class Merger(private val rootFunction: JsFunction, val internalModuleName: JsName, val module: ModuleDescriptor) {
|
||||
// Maps unique signature (see generateSignature) to names
|
||||
private val nameTable = mutableMapOf<String, JsName>()
|
||||
private val importedModuleTable = mutableMapOf<JsImportedModuleKey, JsName>()
|
||||
@@ -114,6 +115,7 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
|
||||
this += importBlock.statements
|
||||
addClassPrototypes(this)
|
||||
this += declarationBlock.statements
|
||||
this += exportBlock.statements
|
||||
this += initializerBlock.statements
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ public final class Translation {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsProgram generateAst(
|
||||
public static AstGenerationResult generateAst(
|
||||
@NotNull BindingTrace bindingTrace,
|
||||
@NotNull Collection<KtFile> files,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
@@ -253,7 +253,7 @@ public final class Translation {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JsProgram doGenerateAst(
|
||||
private static AstGenerationResult doGenerateAst(
|
||||
@NotNull BindingTrace bindingTrace,
|
||||
@NotNull Collection<KtFile> files,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
@@ -263,7 +263,7 @@ public final class Translation {
|
||||
JsProgram program = new JsProgram();
|
||||
JsFunction rootFunction = new JsFunction(program.getRootScope(), new JsBlock(), "root function");
|
||||
JsName internalModuleName = program.getScope().declareName("_");
|
||||
Merger merger = new Merger(rootFunction, internalModuleName);
|
||||
Merger merger = new Merger(rootFunction, internalModuleName, moduleDescriptor);
|
||||
|
||||
List<JsProgramFragment> fragments = new ArrayList<JsProgramFragment>();
|
||||
for (KtFile file : files) {
|
||||
@@ -280,15 +280,13 @@ public final class Translation {
|
||||
|
||||
List<JsStatement> statements = rootBlock.getStatements();
|
||||
|
||||
//staticContext.postProcess();
|
||||
statements.add(0, program.getStringLiteral("use strict").makeStmt());
|
||||
if (!isBuiltinModule(fragments)) {
|
||||
defineModule(program, statements, config.getModuleId());
|
||||
}
|
||||
|
||||
//mayBeGenerateTests(files, rootBlock, context);
|
||||
JsName rootPackageName = program.getScope().declareName(Namer.getRootPackageName());
|
||||
rootFunction.getParameters().add(new JsParameter((rootPackageName)));
|
||||
rootFunction.getParameters().add(new JsParameter(internalModuleName));
|
||||
|
||||
// Invoke function passing modules as arguments
|
||||
// This should help minifier tool to recognize references to these modules as local variables and make them shorter.
|
||||
@@ -307,13 +305,13 @@ public final class Translation {
|
||||
}
|
||||
*/
|
||||
|
||||
statements.add(new JsReturn(rootPackageName.makeRef()));
|
||||
statements.add(new JsReturn(internalModuleName.makeRef()));
|
||||
|
||||
JsBlock block = program.getGlobalBlock();
|
||||
block.getStatements().addAll(wrapIfNecessary(config.getModuleId(), rootFunction, importedModuleList, program,
|
||||
config.getModuleKind()));
|
||||
|
||||
return program;
|
||||
return new AstGenerationResult(program, internalModuleName, fragments, importedModuleList);
|
||||
}
|
||||
|
||||
private static boolean isBuiltinModule(@NotNull List<JsProgramFragment> fragments) {
|
||||
|
||||
+5
-6
@@ -39,13 +39,12 @@ public class VariableAccessTranslator extends AbstractTranslator implements Acce
|
||||
@NotNull KtReferenceExpression referenceExpression,
|
||||
@Nullable JsExpression receiver
|
||||
) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(referenceExpression, context.bindingContext());
|
||||
ResolvedCall<? extends VariableDescriptor> resolvedCall =
|
||||
CallUtilKt.getVariableResolvedCallWithAssert(referenceExpression, context.bindingContext());
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall();
|
||||
}
|
||||
assert resolvedCall.getResultingDescriptor() instanceof VariableDescriptor;
|
||||
return new VariableAccessTranslator(context, referenceExpression, (ResolvedCall<? extends VariableDescriptor>) resolvedCall,
|
||||
receiver);
|
||||
return new VariableAccessTranslator(context, referenceExpression, resolvedCall, receiver);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +74,7 @@ public class VariableAccessTranslator extends AbstractTranslator implements Acce
|
||||
if (InlineUtil.isInline(getter)) {
|
||||
if (e instanceof JsNameRef) {
|
||||
// Get was translated as a name reference
|
||||
setInlineCallMetadata((JsNameRef) e, referenceExpression, getter);
|
||||
setInlineCallMetadata((JsNameRef) e, referenceExpression, getter, context());
|
||||
} else {
|
||||
setInlineCallMetadata(e, referenceExpression, getter, context());
|
||||
}
|
||||
@@ -94,7 +93,7 @@ public class VariableAccessTranslator extends AbstractTranslator implements Acce
|
||||
if (InlineUtil.isInline(setter)) {
|
||||
if (e instanceof JsBinaryOperation && ((JsBinaryOperation) e).getOperator().isAssignment()) {
|
||||
// Set was translated as an assignment
|
||||
setInlineCallMetadata((JsNameRef) (((JsBinaryOperation) e).getArg1()), referenceExpression, setter);
|
||||
setInlineCallMetadata((JsNameRef) (((JsBinaryOperation) e).getArg1()), referenceExpression, setter, context());
|
||||
} else {
|
||||
setInlineCallMetadata(e, referenceExpression, setter, context());
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ fun setInlineCallMetadata(
|
||||
}
|
||||
|
||||
visitor.accept(expression)
|
||||
|
||||
context.addInlineCall(descriptor)
|
||||
}
|
||||
|
||||
fun setInlineCallMetadata(
|
||||
@@ -76,11 +78,14 @@ fun setInlineCallMetadata(
|
||||
fun setInlineCallMetadata(
|
||||
nameRef: JsNameRef,
|
||||
psiElement: KtExpression,
|
||||
descriptor: CallableDescriptor
|
||||
descriptor: CallableDescriptor,
|
||||
context: TranslationContext
|
||||
) {
|
||||
nameRef.descriptor = descriptor
|
||||
nameRef.inlineStrategy = InlineStrategy.IN_PLACE
|
||||
nameRef.psiElement = psiElement
|
||||
|
||||
context.addInlineCall(descriptor)
|
||||
}
|
||||
|
||||
fun TranslationContext.aliasedName(descriptor: CallableDescriptor): JsName {
|
||||
|
||||
Reference in New Issue
Block a user