Skip to content

Commit d1f2255

Browse files
committed
Extract JS-related LibraryUtils utilities to JsLibraryUtils
1 parent f908532 commit d1f2255

File tree

5 files changed

+155
-144
lines changed

5 files changed

+155
-144
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2010-2015 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.jetbrains.kotlin.utils
18+
19+
import com.intellij.openapi.diagnostic.Logger
20+
import com.intellij.openapi.util.io.FileUtil
21+
import com.intellij.util.Processor
22+
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
23+
import java.io.File
24+
import java.io.IOException
25+
import java.util.zip.ZipFile
26+
27+
object JsLibraryUtils {
28+
private val LOG = Logger.getInstance(LibraryUtils::class.java)
29+
30+
private val META_INF_RESOURCES = "${LibraryUtils.META_INF}resources/"
31+
32+
@JvmStatic fun copyJsFilesFromLibraries(libraries: List<String>, outputLibraryJsPath: String) {
33+
for (library in libraries) {
34+
val file = File(library)
35+
assert(file.exists()) { "Library $library not found" }
36+
37+
if (file.isDirectory) {
38+
copyJsFilesFromDirectory(file, outputLibraryJsPath)
39+
}
40+
else {
41+
copyJsFilesFromZip(file, outputLibraryJsPath)
42+
}
43+
}
44+
}
45+
46+
@JvmStatic fun traverseJsLibraries(libs: List<File>, action: (content: String, path: String) -> Unit) {
47+
libs.forEach { traverseJsLibrary(it, action) }
48+
}
49+
50+
@JvmStatic fun traverseJsLibrary(lib: File, action: (content: String, path: String) -> Unit) {
51+
when {
52+
lib.isDirectory -> traverseDirectory(lib, action)
53+
FileUtil.isJarOrZip(lib) -> traverseArchive(lib, action)
54+
lib.name.endsWith(KotlinJavascriptMetadataUtils.JS_EXT) -> {
55+
lib.runIfFileExists(action)
56+
val jsFile = lib.withReplacedExtensionOrNull(
57+
KotlinJavascriptMetadataUtils.META_JS_SUFFIX, KotlinJavascriptMetadataUtils.JS_EXT
58+
)
59+
jsFile?.runIfFileExists(action)
60+
}
61+
else -> throw IllegalArgumentException("Unknown library format (directory, zip or js file expected): $lib")
62+
}
63+
}
64+
65+
private fun File.runIfFileExists(action: (content: String, path: String) -> Unit) {
66+
if (isFile) {
67+
action(FileUtil.loadFile(this), "")
68+
}
69+
}
70+
71+
private fun copyJsFilesFromDirectory(dir: File, outputLibraryJsPath: String) {
72+
traverseDirectory(dir) { content, relativePath ->
73+
FileUtil.writeToFile(File(outputLibraryJsPath, relativePath), content)
74+
}
75+
}
76+
77+
private fun processDirectory(dir: File, action: (content: String, relativePath: String) -> Unit) {
78+
FileUtil.processFilesRecursively(dir, Processor<File> { file ->
79+
val relativePath = FileUtil.getRelativePath(dir, file)
80+
?: throw IllegalArgumentException("relativePath should not be null $dir $file")
81+
if (file.isFile && relativePath.endsWith(KotlinJavascriptMetadataUtils.JS_EXT)) {
82+
val suggestedRelativePath = getSuggestedPath(relativePath) ?: return@Processor true
83+
action(FileUtil.loadFile(file), suggestedRelativePath)
84+
}
85+
true
86+
})
87+
}
88+
89+
private fun traverseDirectory(dir: File, action: (content: String, relativePath: String) -> Unit) {
90+
try {
91+
processDirectory(dir, action)
92+
}
93+
catch (ex: IOException) {
94+
LOG.error("Could not read files from directory ${dir.name}: ${ex.message}")
95+
}
96+
}
97+
98+
private fun copyJsFilesFromZip(file: File, outputLibraryJsPath: String) {
99+
traverseArchive(file) { content, relativePath ->
100+
FileUtil.writeToFile(File(outputLibraryJsPath, relativePath), content)
101+
}
102+
}
103+
104+
private fun traverseArchive(file: File, action: (content: String, relativePath: String) -> Unit) {
105+
val zipFile = ZipFile(file.path)
106+
try {
107+
val zipEntries = zipFile.entries()
108+
while (zipEntries.hasMoreElements()) {
109+
val entry = zipEntries.nextElement()
110+
val entryName = entry.name
111+
if (!entry.isDirectory && entryName.endsWith(KotlinJavascriptMetadataUtils.JS_EXT)) {
112+
val relativePath = getSuggestedPath(entryName) ?: continue
113+
114+
val stream = zipFile.getInputStream(entry)
115+
val content = FileUtil.loadTextAndClose(stream)
116+
action(content, relativePath)
117+
}
118+
}
119+
}
120+
catch (ex: IOException) {
121+
LOG.error("Could not extract files from archive ${file.name}: ${ex.message}")
122+
}
123+
finally {
124+
zipFile.close()
125+
}
126+
}
127+
128+
private fun getSuggestedPath(path: String): String? {
129+
val systemIndependentPath = FileUtil.toSystemIndependentName(path)
130+
if (systemIndependentPath.startsWith(LibraryUtils.META_INF)) {
131+
if (systemIndependentPath.startsWith(META_INF_RESOURCES)) {
132+
return path.substring(META_INF_RESOURCES.length)
133+
}
134+
return null
135+
}
136+
137+
return path
138+
}
139+
}

compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ object KotlinJavascriptMetadataUtils {
3030
const val VFS_PROTOCOL: String = "kotlin-js-meta"
3131
private val KOTLIN_JAVASCRIPT_METHOD_NAME = "kotlin_module_metadata"
3232
private val KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN = "\\.kotlin_module_metadata\\(".toPattern()
33+
3334
/**
3435
* Matches string like <name>.kotlin_module_metadata(<abi version>, <module name>, <base64 data>)
3536
*/
@@ -44,28 +45,13 @@ object KotlinJavascriptMetadataUtils {
4445
@JvmStatic fun hasMetadata(text: String): Boolean =
4546
KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN.matcher(text).find() && METADATA_PATTERN.matcher(text).find()
4647

47-
fun hasMetadataWithIncompatibleAbiVersion(text: String): Boolean {
48-
val matcher = METADATA_PATTERN.matcher(text)
49-
while (matcher.find()) {
50-
var abiVersion = matcher.group(1).toInt()
51-
if (abiVersion != ABI_VERSION) return true
52-
}
53-
return false
54-
}
55-
5648
fun formatMetadataAsString(moduleName: String, content: ByteArray): String =
5749
"// Kotlin.$KOTLIN_JAVASCRIPT_METHOD_NAME($ABI_VERSION, \"$moduleName\", \"${printBase64Binary(content)}\");\n"
5850

5951
@JvmStatic fun loadMetadata(file: File): List<KotlinJavascriptMetadata> {
60-
assert(file.exists()) { "Library " + file + " not found" }
52+
assert(file.exists()) { "Library $file not found" }
6153
val metadataList = arrayListOf<KotlinJavascriptMetadata>()
62-
LibraryUtils.traverseJsLibrary(file) { content, relativePath ->
63-
var path = file.path
64-
65-
if (relativePath.isNotBlank()) {
66-
path += "/$relativePath"
67-
}
68-
54+
JsLibraryUtils.traverseJsLibrary(file) { content, relativePath ->
6955
parseMetadata(content, metadataList)
7056
}
7157

compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt

Lines changed: 9 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,22 @@
1717
package org.jetbrains.kotlin.utils
1818

1919
import com.intellij.openapi.diagnostic.Logger
20-
import com.intellij.openapi.util.io.FileUtil
2120
import com.intellij.openapi.vfs.VirtualFile
22-
import com.intellij.util.Processor
23-
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
2421
import java.io.*
25-
import java.util.Properties
22+
import java.util.*
2623
import java.util.jar.Attributes
2724
import java.util.jar.JarFile
2825
import java.util.jar.Manifest
29-
import java.util.zip.ZipFile
3026

3127
object LibraryUtils {
3228
private val LOG = Logger.getInstance(LibraryUtils::class.java)
3329

3430
val KOTLIN_JS_MODULE_NAME: String = "Kotlin-JS-Module-Name"
3531
private var TITLE_KOTLIN_JAVASCRIPT_STDLIB: String
3632
private var TITLE_KOTLIN_JAVASCRIPT_LIB: String
37-
private val METAINF = "META-INF/"
38-
private val MANIFEST_PATH = "${METAINF}MANIFEST.MF"
39-
private val METAINF_RESOURCES = "${METAINF}resources/"
33+
34+
val META_INF = "META-INF/"
35+
private val MANIFEST_PATH = "${META_INF}MANIFEST.MF"
4036
private val KOTLIN_JS_MODULE_ATTRIBUTE_NAME = Attributes.Name(KOTLIN_JS_MODULE_NAME)
4137

4238
init {
@@ -73,128 +69,20 @@ object LibraryUtils {
7369
}
7470

7571
@JvmStatic fun isOldKotlinJavascriptLibrary(library: File): Boolean =
76-
checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_LIB, Attributes.Name.SPECIFICATION_TITLE) && getKotlinJsModuleName(library) != null
72+
checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_LIB, Attributes.Name.SPECIFICATION_TITLE) &&
73+
getKotlinJsModuleName(library) != null
7774

78-
@JvmStatic fun isKotlinJavascriptLibraryWithMetadata(library: File): Boolean = KotlinJavascriptMetadataUtils.loadMetadata(library).isNotEmpty()
75+
@JvmStatic fun isKotlinJavascriptLibraryWithMetadata(library: File): Boolean =
76+
KotlinJavascriptMetadataUtils.loadMetadata(library).isNotEmpty()
7977

78+
@Suppress("unused") // used in K2JSCompilerMojo
8079
@JvmStatic fun isKotlinJavascriptLibrary(library: File): Boolean =
8180
isOldKotlinJavascriptLibrary(library) || isKotlinJavascriptLibraryWithMetadata(library)
8281

8382
@JvmStatic fun isKotlinJavascriptStdLibrary(library: File): Boolean {
8483
return checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_STDLIB, Attributes.Name.IMPLEMENTATION_TITLE)
8584
}
8685

87-
@JvmStatic fun copyJsFilesFromLibraries(libraries: List<String>, outputLibraryJsPath: String) {
88-
for (library in libraries) {
89-
val file = File(library)
90-
assert(file.exists()) { "Library " + library + " not found" }
91-
92-
if (file.isDirectory) {
93-
copyJsFilesFromDirectory(file, outputLibraryJsPath)
94-
}
95-
else {
96-
copyJsFilesFromZip(file, outputLibraryJsPath)
97-
}
98-
}
99-
}
100-
101-
@JvmStatic fun traverseJsLibraries(libs: List<File>, action: (content: String, path: String)->Unit) {
102-
libs.forEach { traverseJsLibrary(it, action) }
103-
}
104-
105-
@JvmStatic fun traverseJsLibrary(lib: File, action: (content: String, path: String)->Unit) {
106-
when {
107-
lib.isDirectory -> traverseDirectory(lib, action)
108-
FileUtil.isJarOrZip(lib) -> traverseArchive(lib, action)
109-
lib.name.endsWith(KotlinJavascriptMetadataUtils.JS_EXT) -> {
110-
lib.runIfFileExists(action)
111-
val jsFile = lib.withReplacedExtensionOrNull(KotlinJavascriptMetadataUtils.META_JS_SUFFIX, KotlinJavascriptMetadataUtils.JS_EXT)
112-
jsFile?.runIfFileExists(action)
113-
}
114-
else ->
115-
throw IllegalArgumentException("Unknown library format (directory, zip or js file expected): $lib")
116-
}
117-
}
118-
119-
private fun File.runIfFileExists(action: (content: String, path: String)->Unit) {
120-
if (isFile) {
121-
action(FileUtil.loadFile(this), "")
122-
}
123-
}
124-
125-
private fun copyJsFilesFromDirectory(dir: File, outputLibraryJsPath: String) {
126-
traverseDirectory(dir) {
127-
content, relativePath -> FileUtil.writeToFile(File(outputLibraryJsPath, relativePath), content)
128-
}
129-
}
130-
131-
private fun processDirectory(dir: File, action: (content: String, relativePath: String) -> Unit) {
132-
FileUtil.processFilesRecursively(dir, object : Processor<File> {
133-
override fun process(file: File): Boolean {
134-
val relativePath = FileUtil.getRelativePath(dir, file) ?: throw IllegalArgumentException("relativePath should not be null " + dir + " " + file)
135-
if (file.isFile && relativePath.endsWith(KotlinJavascriptMetadataUtils.JS_EXT)) {
136-
val suggestedRelativePath = getSuggestedPath(relativePath)
137-
if (suggestedRelativePath == null) return true
138-
139-
action(FileUtil.loadFile(file), suggestedRelativePath)
140-
}
141-
return true
142-
}
143-
})
144-
}
145-
146-
fun traverseDirectory(dir: File, action: (content: String, relativePath: String) -> Unit) {
147-
try {
148-
processDirectory(dir, action)
149-
}
150-
catch (ex: IOException) {
151-
LOG.error("Could not read files from directory ${dir.name}: ${ex.message}")
152-
}
153-
}
154-
155-
private fun copyJsFilesFromZip(file: File, outputLibraryJsPath: String) {
156-
traverseArchive(file) { content, relativePath ->
157-
FileUtil.writeToFile(File(outputLibraryJsPath, relativePath), content)
158-
}
159-
}
160-
161-
fun traverseArchive(file: File, action: (content: String, relativePath: String) -> Unit) {
162-
val zipFile = ZipFile(file.path)
163-
try {
164-
val zipEntries = zipFile.entries()
165-
while (zipEntries.hasMoreElements()) {
166-
val entry = zipEntries.nextElement()
167-
val entryName = entry.name
168-
if (!entry.isDirectory && entryName.endsWith(KotlinJavascriptMetadataUtils.JS_EXT)) {
169-
val relativePath = getSuggestedPath(entryName)
170-
if (relativePath == null) continue
171-
172-
val stream = zipFile.getInputStream(entry)
173-
val content = FileUtil.loadTextAndClose(stream)
174-
action(content, relativePath)
175-
}
176-
}
177-
}
178-
catch (ex: IOException) {
179-
LOG.error("Could not extract files from archive ${file.name}: ${ex.message}")
180-
}
181-
finally {
182-
zipFile.close()
183-
}
184-
}
185-
186-
private fun getSuggestedPath(path: String): String? {
187-
val systemIndependentPath = FileUtil.toSystemIndependentName(path)
188-
if (systemIndependentPath.startsWith(METAINF)) {
189-
if (systemIndependentPath.startsWith(METAINF_RESOURCES)) {
190-
return path.substring(METAINF_RESOURCES.length)
191-
}
192-
return null
193-
}
194-
195-
return path
196-
}
197-
19886
private fun getManifestFromJar(library: File): Manifest? {
19987
if (!library.canRead()) return null
20088

jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ import org.jetbrains.kotlin.modules.TargetId
6464
import org.jetbrains.kotlin.name.FqName
6565
import org.jetbrains.kotlin.progress.CompilationCanceledException
6666
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
67-
import org.jetbrains.kotlin.utils.LibraryUtils
67+
import org.jetbrains.kotlin.utils.JsLibraryUtils
6868
import org.jetbrains.kotlin.utils.PathUtil
6969
import org.jetbrains.kotlin.utils.keysToMap
7070
import org.jetbrains.kotlin.utils.sure
@@ -592,7 +592,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
592592
val outputLibraryRuntimeDirectory = File(outputDir, compilerSettings.outputDirectoryForJsLibraryFiles).absolutePath
593593
val libraryFilesToCopy = arrayListOf<String>()
594594
JpsJsModuleUtils.getLibraryFiles(representativeTarget, libraryFilesToCopy)
595-
LibraryUtils.copyJsFilesFromLibraries(libraryFilesToCopy, outputLibraryRuntimeDirectory)
595+
JsLibraryUtils.copyJsFilesFromLibraries(libraryFilesToCopy, outputLibraryRuntimeDirectory)
596596
}
597597
}
598598

js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.inline
1919
import com.google.dart.compiler.backend.js.ast.*
2020
import com.google.dart.compiler.backend.js.ast.metadata.inlineStrategy
2121
import com.google.gwt.dev.js.ThrowExceptionOnErrorReporter
22-
import com.intellij.openapi.util.io.FileUtil
2322
import com.intellij.util.containers.SLRUCache
2423
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
2524
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -33,8 +32,7 @@ import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
3332
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getExternalModuleName
3433
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
3534
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
36-
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
37-
import org.jetbrains.kotlin.utils.LibraryUtils
35+
import org.jetbrains.kotlin.utils.JsLibraryUtils
3836
import org.jetbrains.kotlin.utils.sure
3937
import java.io.File
4038

@@ -68,7 +66,7 @@ class FunctionReader(private val context: TranslationContext) {
6866
val config = context.config as LibrarySourcesConfig
6967
val libs = config.libraries.map { File(it) }
7068

71-
LibraryUtils.traverseJsLibraries(libs) { fileContent, path ->
69+
JsLibraryUtils.traverseJsLibraries(libs) { fileContent, path ->
7270
val matcher = DEFINE_MODULE_PATTERN.toPattern().matcher(fileContent)
7371

7472
while (matcher.find()) {

0 commit comments

Comments
 (0)