All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.maven.K2JSCompilerMojo Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.maven;

import com.intellij.openapi.util.text.StringUtil;
import kotlin.collections.CollectionsKt;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
import org.jetbrains.kotlin.cli.js.K2JSCompiler;
import org.jetbrains.kotlin.utils.JsLibraryUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Converts Kotlin to JavaScript code
 *
 * @noinspection UnusedDeclaration
 */
@Mojo(name = "js", defaultPhase = LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
public class K2JSCompilerMojo extends KotlinCompileMojoBase {

    private static final String OUTPUT_DIRECTORIES_COLLECTOR_PROPERTY_NAME = "outputDirectoriesCollector";
    private static final Lock lock = new ReentrantLock();

    /**
     * The output JS file name
     */
    @Parameter(defaultValue = "${project.build.directory}/js/${project.artifactId}.js", required = true)
    private String outputFile;

    /**
     * Flag enables or disables .meta.js and .kjsm files generation, used to create libraries
     */
    @Parameter(defaultValue = "true")
    private boolean metaInfo;

    /**
     * Flags enables or disable source map generation
     */
    @Parameter(defaultValue = "false")
    private boolean sourceMap;

    @Parameter
    private String sourceMapPrefix;

    @Parameter(defaultValue = "inlining")
    private String sourceMapEmbedSources;

    /**
     * Main invocation behaviour. Possible values are call and noCall.
     */
    @Parameter
    private String main;

    /**
     * 

Specifies which JS module system to generate compatible sources for. Options are:

*
    *
  • amd — * Asynchronous Module System;
  • *
  • commonjs — npm/CommonJS conventions based on synchronous require * function;
  • *
  • plain (default) — no module system, keep all modules in global scope;
  • *
  • umd — Universal Module Definition, stub wrapper that detects current * module system in runtime and behaves as plain if none detected.
  • *
*/ @Parameter(defaultValue = "plain") private String moduleKind; @Parameter(defaultValue = "false") private boolean useIrBackend; @Override protected void configureSpecificCompilerArguments(@NotNull K2JSCompilerArguments arguments, @NotNull List sourceRoots) throws MojoExecutionException { arguments.setOutputDir(new File(outputFile).getParent()); arguments.setModuleKind(moduleKind); arguments.setMain(main); arguments.setIrProduceJs(true); arguments.setIrProduceKlibDir(true); List libraries; try { libraries = getKotlinJavascriptLibraryFiles(); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Unresolved dependencies", e); } getLog().debug("libraries: " + libraries); arguments.setLibraries(StringUtil.join(libraries, File.pathSeparator)); arguments.setSourceMap(sourceMap); arguments.setSourceMapPrefix(sourceMapPrefix); arguments.setSourceMapEmbedSources(sourceMapEmbedSources); if (outputFile != null) { ConcurrentMap> collector = getOutputDirectoriesCollector(); String key = project.getArtifactId(); List paths = collector.computeIfAbsent(key, k -> Collections.synchronizedList(new ArrayList<>())); paths.add(new File(outputFile).getParent()); } StringBuilder sourceMapSourceRoots = new StringBuilder(); if (!sourceRoots.isEmpty()) { sourceMapSourceRoots.append(sourceRoots.get(0).getAbsolutePath()); for (int i = 1; i < sourceRoots.size(); ++i) { sourceMapSourceRoots.append(File.pathSeparator); sourceMapSourceRoots.append(sourceRoots.get(i).getAbsolutePath()); } } arguments.setSourceMapBaseDirs(sourceMapSourceRoots.toString()); } protected List getClassPathElements() throws DependencyResolutionRequiredException { return project.getCompileClasspathElements(); } private boolean checkIsKotlinJavascriptLibrary(File file) { return JsLibraryUtils.isKotlinJavascriptIrLibrary(file); } /** * Returns all Kotlin Javascript dependencies that this project has, including transitive ones. * * @return array of paths to kotlin javascript libraries */ @NotNull private List getKotlinJavascriptLibraryFiles() throws DependencyResolutionRequiredException { List libraries = new ArrayList<>(); for (String path : getClassPathElements()) { File file = new File(path); if (file.exists() && checkIsKotlinJavascriptLibrary(file)) { libraries.add(file.getAbsolutePath()); } else { getLog().debug("artifact " + file.getAbsolutePath() + " is not a Kotlin Javascript Library"); } } for (List paths : getOutputDirectoriesCollector().values()) { for (String path : paths) { File file = new File(path); if (file.exists() && checkIsKotlinJavascriptLibrary(file)) { libraries.add(file.getAbsolutePath()); } else { getLog().debug("JS output directory missing: " + file); } } } return libraries; } @NotNull @Override protected K2JSCompilerArguments createCompilerArguments() { return new K2JSCompilerArguments(); } @Override protected List getRelatedSourceRoots(MavenProject project) { return project.getCompileSourceRoots(); } @NotNull @Override protected K2JSCompiler createCompiler() { return new K2JSCompiler(); } @SuppressWarnings("unchecked") protected ConcurrentMap> getOutputDirectoriesCollector() { lock.lock(); try { ConcurrentMap> collector = (ConcurrentMap>) getPluginContext().get(OUTPUT_DIRECTORIES_COLLECTOR_PROPERTY_NAME); if (collector == null) { collector = new ConcurrentSkipListMap<>(); getPluginContext().put(OUTPUT_DIRECTORIES_COLLECTOR_PROPERTY_NAME, collector); } return collector; } finally { lock.unlock(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy