JS: support internal visibility from friend modules

Friend modules should be provided using the -Xfriend-modules flag
in the same format as -libraries. No manual configuration required for
JPS, Gradle and Maven plugins.

Friend modules could be switched off using the -Xfriend-modules-disabled
flag. Doing that will
  * prevent internal declarations from being exported,
  * values provided by -Xfriend-modules ignored,
  * raise a compilation error on attemps to use internal declarations from other modules

Fixes #KT-15135 and #KT-16568.
This commit is contained in:
Anton Bannykh
2017-03-30 15:03:38 +03:00
parent 7bbf9861d0
commit 2e9a59819a
48 changed files with 765 additions and 133 deletions
@@ -34,9 +34,11 @@ import org.jetbrains.kotlin.js.JavaScript;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -109,15 +111,11 @@ public class K2JSCompilerMojo extends KotlinCompileMojoBase<K2JSCompilerArgument
arguments.sourceMap = sourceMap;
Set<String> collector = getOutputDirectoriesCollector();
if (outputFile != null) {
collector.add(new File(outputFile).getParent());
}
if (metaInfo) {
String output = com.google.common.base.Objects.firstNonNull(outputFile, ""); // fqname here because of J8 compatibility issues
String metaFile = StringsKt.substringBeforeLast(output, JavaScript.DOT_EXTENSION, output) + KotlinJavascriptMetadataUtils.META_JS_SUFFIX;
collector.add(new File(metaFile).getParent());
ConcurrentMap<String, List<String>> collector = getOutputDirectoriesCollector();
String key = project.getArtifactId();
List<String> paths = collector.computeIfAbsent(key, k -> Collections.synchronizedList(new ArrayList<String>()));
paths.add(new File(outputFile).getParent());
}
}
@@ -145,14 +143,16 @@ public class K2JSCompilerMojo extends KotlinCompileMojoBase<K2JSCompilerArgument
}
}
for (String path : getOutputDirectoriesCollector()) {
File file = new File(path);
for (List<String> paths : getOutputDirectoriesCollector().values()) {
for (String path : paths) {
File file = new File(path);
if (file.exists() && LibraryUtils.isKotlinJavascriptLibrary(file)) {
libraries.add(file.getAbsolutePath());
}
else {
getLog().debug("JS output directory missing: " + file);
if (file.exists() && LibraryUtils.isKotlinJavascriptLibrary(file)) {
libraries.add(file.getAbsolutePath());
}
else {
getLog().debug("JS output directory missing: " + file);
}
}
}
@@ -177,12 +177,12 @@ public class K2JSCompilerMojo extends KotlinCompileMojoBase<K2JSCompilerArgument
}
@SuppressWarnings("unchecked")
private Set<String> getOutputDirectoriesCollector() {
protected ConcurrentMap<String, List<String>> getOutputDirectoriesCollector() {
lock.lock();
try {
Set<String> collector = (Set<String>) getPluginContext().get(OUTPUT_DIRECTORIES_COLLECTOR_PROPERTY_NAME);
ConcurrentMap<String, List<String>> collector = (ConcurrentMap<String, List<String>>) getPluginContext().get(OUTPUT_DIRECTORIES_COLLECTOR_PROPERTY_NAME);
if (collector == null) {
collector = new ConcurrentSkipListSet<String>();
collector = new ConcurrentSkipListMap<String, List<String>>();
getPluginContext().put(OUTPUT_DIRECTORIES_COLLECTOR_PROPERTY_NAME, collector);
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.maven;
import com.intellij.openapi.util.text.StringUtil;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -27,8 +28,9 @@ import org.apache.maven.project.MavenProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
import java.io.File;
import java.util.List;
import java.util.Collections;
/**
* Converts Kotlin to JavaScript code
*
@@ -79,6 +81,8 @@ public class KotlinTestJSCompilerMojo extends K2JSCompilerMojo {
@Override
protected void configureSpecificCompilerArguments(@NotNull K2JSCompilerArguments arguments) throws MojoExecutionException {
List<String> friends = getOutputDirectoriesCollector().getOrDefault(project.getArtifactId(), Collections.emptyList());
arguments.friendModules = StringUtil.join(friends, File.pathSeparator);
output = testOutput;
super.configureSpecificCompilerArguments(arguments);