From c0739ef53c6fecccede925de7fbc57ca88693257 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Sun, 8 Nov 2015 19:54:46 +0300 Subject: [PATCH] Add prefix information for Java source root (KT-9167 in progress) #KT-9167 In Progress --- .../cli/common/modules/ModuleBuilder.kt | 9 ++++---- .../cli/common/modules/ModuleXmlParser.java | 12 ++++++++++- .../cli/jvm/compiler/JvmDependenciesIndex.kt | 18 +++++++++------- .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 16 +++++++++++++- .../compiler/KotlinToJVMBytecodeCompiler.java | 5 +++-- .../kotlin/cli/jvm/config/JvmContentRoots.kt | 10 +++++---- .../org/jetbrains/kotlin/modules/Module.kt | 4 +++- .../kotlin/jps/build/JvmSourceRoot.kt | 21 +++++++++++++++++++ .../KotlinBuilderModuleScriptGenerator.java | 7 ++++--- .../modules/KotlinModuleXmlBuilder.java | 17 +++++++++++---- .../kotlin/jvm/compiler/ClasspathOrderTest.kt | 3 ++- .../modules/KotlinModuleXmlGeneratorTest.java | 9 ++++---- 12 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 jps-plugin/src/org/jetbrains/kotlin/jps/build/JvmSourceRoot.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleBuilder.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleBuilder.kt index 541de5eb997..e27fe329cca 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleBuilder.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleBuilder.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.cli.common.modules import org.jetbrains.kotlin.modules.Module +import org.jetbrains.kotlin.modules.JavaRootPath import java.util.* public class ModuleBuilder( @@ -26,7 +27,7 @@ public class ModuleBuilder( ) : Module { private val sourceFiles = ArrayList() private val classpathRoots = ArrayList() - private val javaSourceRoots = ArrayList() + private val javaSourceRoots = ArrayList() public fun addSourceFiles(pattern: String) { sourceFiles.add(pattern) @@ -36,12 +37,12 @@ public class ModuleBuilder( classpathRoots.add(name) } - public fun addJavaSourceRoot(name: String) { - javaSourceRoots.add(name) + public fun addJavaSourceRoot(rootPath: JavaRootPath) { + javaSourceRoots.add(rootPath) } override fun getOutputDirectory(): String = outputDir - override fun getJavaSourceRoots(): List = javaSourceRoots + override fun getJavaSourceRoots(): List = javaSourceRoots override fun getSourceFiles(): List = sourceFiles override fun getClasspathRoots(): List = classpathRoots override fun getModuleName(): String = name diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleXmlParser.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleXmlParser.java index 5bcc0286f2f..8a3b845dd95 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleXmlParser.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/modules/ModuleXmlParser.java @@ -19,9 +19,11 @@ package org.jetbrains.kotlin.cli.common.modules; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil; import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil; +import org.jetbrains.kotlin.modules.JavaRootPath; import org.jetbrains.kotlin.modules.Module; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -47,6 +49,7 @@ public class ModuleXmlParser { public static final String OUTPUT_DIR = "outputDir"; public static final String SOURCES = "sources"; public static final String JAVA_SOURCE_ROOTS = "javaSourceRoots"; + public static final String JAVA_SOURCE_PACKAGE_PREFIX = "packagePrefix"; public static final String PATH = "path"; public static final String CLASSPATH = "classpath"; @@ -165,7 +168,8 @@ public class ModuleXmlParser { } else if (JAVA_SOURCE_ROOTS.equalsIgnoreCase(qName)) { String path = getAttribute(attributes, PATH, qName); - moduleBuilder.addJavaSourceRoot(path); + String packagePrefix = getNullableAttribute(attributes, JAVA_SOURCE_PACKAGE_PREFIX); + moduleBuilder.addJavaSourceRoot(new JavaRootPath(path, packagePrefix)); } else { throw createError(qName); @@ -189,6 +193,12 @@ public class ModuleXmlParser { return name; } + @Nullable + private static String getNullableAttribute(Attributes attributes, String qName) throws SAXException { + return attributes.getValue(qName); + } + + private static SAXException createError(String qName) throws SAXException { return new SAXException("Unexpected tag: " + qName); } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt index f699851aaa0..22d7fb8a2fa 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt @@ -24,7 +24,7 @@ import java.util.ArrayList import java.util.EnumSet import java.util.HashMap -public data class JavaRoot(public val file: VirtualFile, public val type: JavaRoot.RootType) { +public data class JavaRoot(public val file: VirtualFile, public val type: JavaRoot.RootType, public val prefixFqName: FqName? = null) { public enum class RootType { SOURCE, BINARY @@ -45,7 +45,7 @@ public class JvmDependenciesIndex(_roots: List) { private val roots: List by lazy { _roots.toList() } private val maxIndex: Int - get() = roots.size() + get() = roots.size // each "Cache" object corresponds to a package private class Cache { @@ -112,10 +112,12 @@ public class JvmDependenciesIndex(_roots: List) { if (request !is FindClassRequest || lastClassSearch == null) { return doSearch() } + val (cachedRequest, cachedResult) = lastClassSearch!! if (cachedRequest.classId != request.classId) { return doSearch() } + when (cachedResult) { is SearchResult.NotFound -> { val limitedRootTypes = request.acceptedRootTypes.toHashSet() @@ -165,7 +167,7 @@ public class JvmDependenciesIndex(_roots: List) { } // a list of package sub names, ["org", "jb", "kotlin"] - val packagesPath = request.packageFqName.pathSegments().map { it.getIdentifier() } + val packagesPath = request.packageFqName.pathSegments().map { it.identifier } // a list of caches corresponding to packages, [default, "org", "org.jb", "org.jb.kotlin"] val caches = cachesPath(packagesPath) @@ -190,6 +192,7 @@ public class JvmDependenciesIndex(_roots: List) { } processedRootsUpTo = cache.rootIndices.lastOrNull() ?: processedRootsUpTo } + return notFound() } @@ -197,7 +200,7 @@ public class JvmDependenciesIndex(_roots: List) { // possibly filling "Cache" objects with new information private fun travelPath(rootIndex: Int, packagesPath: List, fillCachesAfter: Int, cachesPath: List): VirtualFile? { if (rootIndex >= maxIndex) { - for (i in (fillCachesAfter + 1)..cachesPath.size() - 1) { + for (i in (fillCachesAfter + 1)..(cachesPath.size - 1)) { // we all know roots that contain this package by now cachesPath[i].rootIndices.add(maxIndex) cachesPath[i].rootIndices.trimToSize() @@ -215,6 +218,7 @@ public class JvmDependenciesIndex(_roots: List) { cachesPath[correspondingCacheIndex].rootIndices.add(rootIndex) } } + return currentFile } @@ -231,7 +235,7 @@ public class JvmDependenciesIndex(_roots: List) { private data class FindClassRequest(val classId: ClassId, override val acceptedRootTypes: Set) : SearchRequest { override val packageFqName: FqName - get() = classId.getPackageFqName() + get() = classId.packageFqName } private data class TraverseRequest( @@ -251,5 +255,5 @@ public class JvmDependenciesIndex(_roots: List) { } } -private fun IntArrayList.lastOrNull() = if (isEmpty()) null else get(size() - 1) -private val IntArrayList.indices: IntRange get() = 0..size()-1 \ No newline at end of file +private fun IntArrayList.lastOrNull() = if (isEmpty) null else get(size() - 1) +private val IntArrayList.indices: IntRange get() = 0..(size() - 1) \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index b5c842e309b..8e651435738 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -75,6 +75,8 @@ import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinderFactory import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.isValidJavaFqName import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.parsing.KotlinScriptDefinitionProvider import org.jetbrains.kotlin.psi.KtFile @@ -167,12 +169,24 @@ public class KotlinCoreEnvironment private constructor( val virtualFile = contentRootToVirtualFile(javaRoot) ?: continue projectEnvironment.addSourcesToClasspath(virtualFile) + + val prefixPackageFqName = (javaRoot as? JavaSourceRoot)?.packagePrefix?.let { + if (isValidJavaFqName(it)) { + FqName(it) + } + else { + report(WARNING, "Invalid package prefix name is ignored: $it") + null + } + } + val rootType = when (javaRoot) { is JavaSourceRoot -> JavaRoot.RootType.SOURCE is JvmClasspathRoot -> JavaRoot.RootType.BINARY else -> throw IllegalStateException() } - javaRoots.add(JavaRoot(virtualFile, rootType)) + + javaRoots.add(JavaRoot(virtualFile, rootType, prefixPackageFqName)) } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java index 8168d06dcb9..d1c0eca8c53 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java @@ -49,6 +49,7 @@ import org.jetbrains.kotlin.idea.MainFunctionDetector; import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager; import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache; import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents; +import org.jetbrains.kotlin.modules.JavaRootPath; import org.jetbrains.kotlin.modules.Module; import org.jetbrains.kotlin.modules.TargetId; import org.jetbrains.kotlin.modules.TargetIdKt; @@ -183,8 +184,8 @@ public class KotlinToJVMBytecodeCompiler { } for (Module module : chunk) { - for (String javaSourceRoot : module.getJavaSourceRoots()) { - JvmContentRootsKt.addJavaSourceRoot(configuration, new File(javaSourceRoot)); + for (JavaRootPath javaRootPath : module.getJavaSourceRoots()) { + JvmContentRootsKt.addJavaSourceRoot(configuration, new File(javaRootPath.getPath()), javaRootPath.getPackagePrefix()); } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/JvmContentRoots.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/JvmContentRoots.kt index 4bc18d7e2f9..03f2b9e9f32 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/JvmContentRoots.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/JvmContentRoots.kt @@ -23,7 +23,7 @@ import java.io.File public data class JvmClasspathRoot(public override val file: File): JvmContentRoot -public data class JavaSourceRoot(public override val file: File): JvmContentRoot +public data class JavaSourceRoot(public override val file: File, public val packagePrefix: String?): JvmContentRoot public interface JvmContentRoot : ContentRoot { public val file: File @@ -40,8 +40,10 @@ public val CompilerConfiguration.jvmClasspathRoots: List return get(CommonConfigurationKeys.CONTENT_ROOTS)?.filterIsInstance()?.map { it.file } ?: emptyList() } -public fun CompilerConfiguration.addJavaSourceRoot(file: File) { - add(CommonConfigurationKeys.CONTENT_ROOTS, JavaSourceRoot(file)) +@JvmOverloads +public fun CompilerConfiguration.addJavaSourceRoot(file: File, packagePrefix: String? = null) { + add(CommonConfigurationKeys.CONTENT_ROOTS, JavaSourceRoot(file, packagePrefix)) } -public fun CompilerConfiguration.addJavaSourceRoots(files: List): Unit = files.forEach { addJavaSourceRoot(it) } \ No newline at end of file +@JvmOverloads +public fun CompilerConfiguration.addJavaSourceRoots(files: List, packagePrefix: String? = null): Unit = files.forEach { addJavaSourceRoot(it, packagePrefix) } \ No newline at end of file diff --git a/compiler/util/src/org/jetbrains/kotlin/modules/Module.kt b/compiler/util/src/org/jetbrains/kotlin/modules/Module.kt index 45a81f619c9..724a97100e6 100644 --- a/compiler/util/src/org/jetbrains/kotlin/modules/Module.kt +++ b/compiler/util/src/org/jetbrains/kotlin/modules/Module.kt @@ -27,5 +27,7 @@ public interface Module { public fun getClasspathRoots(): List - public fun getJavaSourceRoots(): List + public fun getJavaSourceRoots(): List } + +data class JavaRootPath(val path: String, val packagePrefix: String? = null) diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/JvmSourceRoot.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/JvmSourceRoot.kt new file mode 100644 index 00000000000..6dba446f049 --- /dev/null +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/JvmSourceRoot.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2015 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.jps.build + +import java.io.File + +data class JvmSourceRoot(val file: File, val packagePrefix: String? = null) diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.java b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.java index 3425490f7c7..6d146f3274f 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.java +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.java @@ -127,13 +127,14 @@ public class KotlinBuilderModuleScriptGenerator { } @NotNull - private static List findSourceRoots(@NotNull CompileContext context, @NotNull ModuleBuildTarget target) { + private static List findSourceRoots(@NotNull CompileContext context, @NotNull ModuleBuildTarget target) { List roots = context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context); - List result = ContainerUtil.newArrayList(); + List result = ContainerUtil.newArrayList(); for (JavaSourceRootDescriptor root : roots) { File file = root.getRootFile(); + String prefix = root.getPackagePrefix(); if (file.exists()) { - result.add(file); + result.add(new JvmSourceRoot(file, prefix.isEmpty() ? null : prefix)); } } return result; diff --git a/jps-plugin/src/org/jetbrains/kotlin/modules/KotlinModuleXmlBuilder.java b/jps-plugin/src/org/jetbrains/kotlin/modules/KotlinModuleXmlBuilder.java index a74c1a2f29b..73cdd88fd4b 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/modules/KotlinModuleXmlBuilder.java +++ b/jps-plugin/src/org/jetbrains/kotlin/modules/KotlinModuleXmlBuilder.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.modules; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.kotlin.config.IncrementalCompilation; +import org.jetbrains.kotlin.jps.build.JvmSourceRoot; import org.jetbrains.kotlin.utils.Printer; import java.io.File; @@ -43,7 +44,7 @@ public class KotlinModuleXmlBuilder { String moduleName, String outputDir, List sourceFiles, - List javaSourceRoots, + List javaSourceRoots, Collection classpathRoots, JavaModuleBuildTargetType targetType, Set directoriesToFilterOut @@ -100,10 +101,18 @@ public class KotlinModuleXmlBuilder { } } - private void processJavaSourceRoots(@NotNull List files) { + private void processJavaSourceRoots(@NotNull List roots) { p.println(""); - for (File file : files) { - p.println("<", JAVA_SOURCE_ROOTS, " ", PATH, "=\"", getEscapedPath(file), "\"/>"); + for (JvmSourceRoot root : roots) { + p.print("<"); + p.printWithNoIndent(JAVA_SOURCE_ROOTS, " ", PATH, "=\"", getEscapedPath(root.getFile()), "\""); + + if (root.getPackagePrefix() != null) { + p.printWithNoIndent(" ", JAVA_SOURCE_PACKAGE_PREFIX, "=\"", root.getPackagePrefix(), "\""); + } + + p.printWithNoIndent("/>"); + p.println(); } } diff --git a/jps-plugin/test/org/jetbrains/kotlin/jvm/compiler/ClasspathOrderTest.kt b/jps-plugin/test/org/jetbrains/kotlin/jvm/compiler/ClasspathOrderTest.kt index 7a9f6cfc73b..67d05520359 100644 --- a/jps-plugin/test/org/jetbrains/kotlin/jvm/compiler/ClasspathOrderTest.kt +++ b/jps-plugin/test/org/jetbrains/kotlin/jvm/compiler/ClasspathOrderTest.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.jvm.compiler import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType +import org.jetbrains.kotlin.jps.build.JvmSourceRoot import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.MockLibraryUtil @@ -43,7 +44,7 @@ public class ClasspathOrderTest : TestCaseWithTmpdir() { "name", File(tmpdir, "output").getAbsolutePath(), listOf(sourceDir), - listOf(sourceDir), + listOf(JvmSourceRoot(sourceDir)), listOf(PathUtil.getKotlinPathsForDistDirectory().getRuntimePath()), JavaModuleBuildTargetType.PRODUCTION, setOf() diff --git a/jps-plugin/test/org/jetbrains/kotlin/modules/KotlinModuleXmlGeneratorTest.java b/jps-plugin/test/org/jetbrains/kotlin/modules/KotlinModuleXmlGeneratorTest.java index b6198737e3e..a16f2d3ce01 100644 --- a/jps-plugin/test/org/jetbrains/kotlin/modules/KotlinModuleXmlGeneratorTest.java +++ b/jps-plugin/test/org/jetbrains/kotlin/modules/KotlinModuleXmlGeneratorTest.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.modules; import junit.framework.TestCase; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; +import org.jetbrains.kotlin.jps.build.JvmSourceRoot; import org.jetbrains.kotlin.test.KotlinTestUtils; import java.io.File; @@ -30,7 +31,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { "name", "output", Arrays.asList(new File("s1"), new File("s2")), - Collections.singletonList(new File("java")), + Collections.singletonList(new JvmSourceRoot(new File("java"), null)), Arrays.asList(new File("cp1"), new File("cp2")), JavaModuleBuildTargetType.PRODUCTION, Collections.emptySet() @@ -43,7 +44,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { "name", "output", Arrays.asList(new File("s1"), new File("s2")), - Collections.emptyList(), + Collections.emptyList(), Arrays.asList(new File("cp1"), new File("cp2")), JavaModuleBuildTargetType.PRODUCTION, Collections.singleton(new File("cp1")) @@ -57,7 +58,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { "name", "output", Arrays.asList(new File("s1"), new File("s2")), - Collections.emptyList(), + Collections.emptyList(), Arrays.asList(new File("cp1"), new File("cp2")), JavaModuleBuildTargetType.PRODUCTION, Collections.singleton(new File("cp1")) @@ -66,7 +67,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { "name2", "output2", Arrays.asList(new File("s12"), new File("s22")), - Collections.emptyList(), + Collections.emptyList(), Arrays.asList(new File("cp12"), new File("cp22")), JavaModuleBuildTargetType.TEST, Collections.singleton(new File("cp12"))