Skip to content

Commit 1489f0f

Browse files
timothyklimcopybara-github
authored andcommitted
Support Scala3 .tasty files
**ijar** tool support Kotlin modules by [not stripped out](bazelbuild@088d8de) files in `META-INF/*.kotlin_module`. This PR add support for new Scala 3 (and Scala 2.13.4+) [TASTy](https://dotty.epfl.ch/docs/reference/metaprogramming/toc.html) format to have ability to use Scala 3 modules. Closes bazelbuild#12529. PiperOrigin-RevId: 346068234
1 parent 1b02aca commit 1489f0f

File tree

4 files changed

+89
-3
lines changed

4 files changed

+89
-3
lines changed

third_party/ijar/ijar.cc

+11-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const char *CLASS_EXTENSION = ".class";
3737
const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION);
3838
const char *KOTLIN_MODULE_EXTENSION = ".kotlin_module";
3939
const size_t KOTLIN_MODULE_EXTENSION_LENGTH = strlen(KOTLIN_MODULE_EXTENSION);
40+
const char *SCALA_TASTY_EXTENSION = ".tasty";
41+
const size_t SCALA_TASTY_EXTENSION_LENGTH = strlen(SCALA_TASTY_EXTENSION);
4042

4143
const char *MANIFEST_DIR_PATH = "META-INF/";
4244
const size_t MANIFEST_DIR_PATH_LENGTH = strlen(MANIFEST_DIR_PATH);
@@ -101,9 +103,15 @@ static bool IsKotlinModule(const char *filename, const size_t filename_len) {
101103
KOTLIN_MODULE_EXTENSION_LENGTH);
102104
}
103105

106+
static bool IsScalaTasty(const char *filename, const size_t filename_len) {
107+
return EndsWith(filename, filename_len, SCALA_TASTY_EXTENSION,
108+
SCALA_TASTY_EXTENSION_LENGTH);
109+
}
110+
104111
bool JarStripperProcessor::Accept(const char *filename, const u4 /*attr*/) {
105112
const size_t filename_len = strlen(filename);
106-
if (IsKotlinModule(filename, filename_len)) {
113+
if (IsKotlinModule(filename, filename_len) ||
114+
IsScalaTasty(filename, filename_len)) {
107115
return true;
108116
}
109117
if (filename_len < CLASS_EXTENSION_LENGTH ||
@@ -129,7 +137,8 @@ void JarStripperProcessor::Process(const char *filename, const u4 /*attr*/,
129137
if (verbose) {
130138
fprintf(stderr, "INFO: StripClass: %s\n", filename);
131139
}
132-
if (IsModuleInfo(filename) || IsKotlinModule(filename, strlen(filename))) {
140+
if (IsModuleInfo(filename) || IsKotlinModule(filename, strlen(filename)) ||
141+
IsScalaTasty(filename, strlen(filename))) {
133142
u1 *q = builder_->NewFile(filename, 0);
134143
memcpy(q, data, size);
135144
builder_->FinishFile(size, /* compress: */ false, /* compute_crc: */ true);

third_party/ijar/test/BUILD

+26
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,31 @@ genrule(
267267
tools = ["//third_party/ijar"],
268268
)
269269

270+
java_binary(
271+
name = "GenScalaTasty",
272+
testonly = 1,
273+
srcs = ["GenScalaTasty.java"],
274+
main_class = "GenScalaTasty",
275+
deps = ["//third_party:guava"],
276+
)
277+
278+
genrule(
279+
name = "scala_tasty",
280+
testonly = 1,
281+
outs = ["scala_tasty.jar"],
282+
cmd = "$(location :GenScalaTasty) $@",
283+
tools = [":GenScalaTasty"],
284+
)
285+
286+
genrule(
287+
name = "scala_tasty-interface",
288+
testonly = 1,
289+
srcs = [":scala_tasty.jar"],
290+
outs = ["scala_tasty-interface.jar"],
291+
cmd = "$(location //third_party/ijar) $< $@",
292+
tools = ["//third_party/ijar"],
293+
)
294+
270295
java_test(
271296
name = "IjarTests",
272297
size = "small",
@@ -295,6 +320,7 @@ java_test(
295320
":liblocal_and_anonymous_lib.jar",
296321
":local_and_anonymous-interface.jar",
297322
":module_info-interface.jar",
323+
":scala_tasty-interface.jar",
298324
],
299325
tags = ["zip"],
300326
test_class = "IjarTests",
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2020 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import static java.nio.charset.StandardCharsets.UTF_8;
16+
17+
import com.google.common.io.ByteStreams;
18+
import java.io.IOException;
19+
import java.nio.file.Files;
20+
import java.nio.file.Paths;
21+
import java.util.jar.JarOutputStream;
22+
import java.util.zip.ZipEntry;
23+
24+
/** A generator for a jar file containing a .tasty file, and one real class file. */
25+
public class GenScalaTasty {
26+
public static void main(String[] args) throws IOException {
27+
try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(Paths.get(args[0])))) {
28+
addEntry(jos, "Bar.tasty");
29+
jos.write("hello".getBytes(UTF_8));
30+
31+
addEntry(jos, "java/lang/String.class");
32+
ByteStreams.copy(String.class.getResourceAsStream("/java/lang/String.class"), jos);
33+
}
34+
}
35+
36+
private static void addEntry(JarOutputStream jos, String name) throws IOException {
37+
ZipEntry ze = new ZipEntry(name);
38+
ze.setTime(0);
39+
jos.putNextEntry(ze);
40+
}
41+
}

third_party/ijar/test/IjarTests.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ static Map<String, byte[]> readJar(String path) throws IOException {
248248
Enumeration<JarEntry> entries = jf.entries();
249249
while (entries.hasMoreElements()) {
250250
JarEntry je = entries.nextElement();
251-
if (!je.getName().endsWith(".class") && !je.getName().endsWith(".kotlin_module")) {
251+
if (!je.getName().endsWith(".class")
252+
&& !je.getName().endsWith(".kotlin_module")
253+
&& !je.getName().endsWith(".tasty")) {
252254
continue;
253255
}
254256
classes.put(je.getName(), ByteStreams.toByteArray(jf.getInputStream(je)));
@@ -291,6 +293,14 @@ public void kotlinModule() throws Exception {
291293
assertThat(new String(lib.get("META-INF/bar.kotlin_module"), UTF_8)).isEqualTo("hello");
292294
}
293295

296+
@Test
297+
public void scalaTasty() throws Exception {
298+
Map<String, byte[]> lib = readJar("third_party/ijar/test/scala_tasty-interface.jar");
299+
assertThat(lib.keySet()).containsExactly("java/lang/String.class", "Bar.tasty");
300+
// ijar passes scala tasty files through unmodified
301+
assertThat(new String(lib.get("Bar.tasty"), UTF_8)).isEqualTo("hello");
302+
}
303+
294304
@Test
295305
public void testTargetLabel() throws Exception {
296306
try (JarFile jf =

0 commit comments

Comments
 (0)