Skip to content

Commit 6dd98a1

Browse files
authored
Upgrade to Scala 2.13.12 (#1517)
1 parent acebcfe commit 6dd98a1

File tree

14 files changed

+368
-27
lines changed

14 files changed

+368
-27
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,13 @@ Previous minor versions may work but are supported only on a best effort basis.
145145
To configure Scala version you must call `scala_config(scala_version = "2.xx.xx")` and configure
146146
dependencies by declaring [scala_toolchain](docs/scala_toolchain.md).
147147
For a quick start you can use `scala_repositories()` and `scala_register_toolchains()`, which have
148-
dependency providers configured for `2.11.12`, `2.12.18` and `2.13.11` versions.
148+
dependency providers configured for `2.11.12`, `2.12.18` and `2.13.12` versions.
149149

150150

151151
```starlark
152152
# WORKSPACE
153153
load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config")
154-
scala_config(scala_version = "2.13.11")
154+
scala_config(scala_version = "2.13.12")
155155

156156
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
157157
rules_proto_dependencies()

dt_patches/dt_patch_test.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ run_test_local test_compiler_patch 2.13.7
109109
run_test_local test_compiler_patch 2.13.8
110110
run_test_local test_compiler_patch 2.13.10
111111
run_test_local test_compiler_patch 2.13.11
112+
run_test_local test_compiler_patch 2.13.12
112113

113114
run_test_local test_compiler_srcjar_error 2.12.11
114115
run_test_local test_compiler_srcjar_error 2.12.12
@@ -120,4 +121,7 @@ run_test_local test_compiler_srcjar 2.12.14
120121
run_test_local test_compiler_srcjar 2.12.15
121122
run_test_local test_compiler_srcjar 2.12.16
122123
run_test_local test_compiler_srcjar_nonhermetic 2.12.17
123-
run_test_local test_compiler_srcjar_nonhermetic 2.12.18
124+
run_test_local test_compiler_srcjar_nonhermetic 2.12.18
125+
126+
run_test_local test_compiler_srcjar_nonhermetic 2.13.11
127+
run_test_local test_compiler_srcjar_nonhermetic 2.13.12

dt_patches/test_dt_patches_user_srcjar/WORKSPACE

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ srcjars_by_version = {
9191
"2.12.18": {
9292
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.12.18/scala-compiler-2.12.18-sources.jar?foo",
9393
},
94+
"2.13.11": {
95+
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.11/scala-compiler-2.13.11-sources.jar?foo",
96+
},
97+
"2.13.12": {
98+
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.12/scala-compiler-2.13.12-sources.jar?foo",
99+
},
94100
}
95101

96102
rules_scala_setup(scala_compiler_srcjar = srcjars_by_version[SCALA_VERSION])

examples/semanticdb/WORKSPACE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ local_repository(
2121

2222
load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config")
2323

24-
scala_config(scala_version = "2.13.11")
24+
scala_config(scala_version = "2.13.12")
2525

2626
load(
2727
"@io_bazel_rules_scala//scala:scala.bzl",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
load("@io_bazel_rules_scala_config//:config.bzl", "SCALA_MAJOR_VERSION", "SCALA_MINOR_VERSION")
2+
3+
filegroup(
4+
name = "deps_tracking_reporter",
5+
srcs = [
6+
"before_2_13_12/DepsTrackingReporter.java",
7+
] if SCALA_MAJOR_VERSION.startswith("2.11") or SCALA_MAJOR_VERSION.startswith("2.12") or (SCALA_MAJOR_VERSION.startswith("2.13") and int(SCALA_MINOR_VERSION) < 12) else [
8+
"after_2_13_12/DepsTrackingReporter.java",
9+
],
10+
visibility = ["//visibility:public"],
11+
)
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
package io.bazel.rulesscala.scalac.reporter;
2+
3+
import io.bazel.rulesscala.deps.proto.ScalaDeps;
4+
import io.bazel.rulesscala.deps.proto.ScalaDeps.Dependency;
5+
import io.bazel.rulesscala.deps.proto.ScalaDeps.Dependency.Kind;
6+
import io.bazel.rulesscala.scalac.compileoptions.CompileOptions;
7+
import java.io.BufferedOutputStream;
8+
import java.io.IOException;
9+
import java.io.OutputStream;
10+
import java.nio.file.Files;
11+
import java.nio.file.Paths;
12+
import java.util.Arrays;
13+
import java.util.Collection;
14+
import java.util.HashMap;
15+
import java.util.HashSet;
16+
import java.util.Map;
17+
import java.util.Set;
18+
import java.util.jar.JarFile;
19+
import java.util.stream.Collectors;
20+
import scala.collection.immutable.List$;
21+
import scala.reflect.internal.util.CodeAction;
22+
import scala.reflect.internal.util.NoPosition$;
23+
import scala.reflect.internal.util.Position;
24+
import scala.tools.nsc.Settings;
25+
import scala.tools.nsc.reporters.ConsoleReporter;
26+
import scala.tools.nsc.reporters.Reporter;
27+
28+
import javax.print.attribute.standard.Severity;
29+
30+
public class DepsTrackingReporter extends ConsoleReporter {
31+
32+
private static final String HJAR_JAR_SUFFIX = "-hjar.jar";
33+
private static final String IJAR_JAR_SUFFIX = "-ijar.jar";
34+
private final Set<String> usedJars = new HashSet<>();
35+
36+
private final Map<String, String> jarToTarget = new HashMap<>();
37+
private final Map<String, String> indirectJarToTarget = new HashMap<>();
38+
39+
private final Set<String> ignoredTargets;
40+
private final Set<String> directTargets;
41+
42+
private final CompileOptions ops;
43+
public final Reporter delegateReporter;
44+
private Set<String> astUsedJars = new HashSet<>();
45+
46+
public DepsTrackingReporter(Settings settings, CompileOptions ops, Reporter delegate) {
47+
super(settings);
48+
this.ops = ops;
49+
this.delegateReporter = delegate;
50+
51+
if (ops.directJars.length == ops.directTargets.length) {
52+
for (int i = 0; i < ops.directJars.length; i++) {
53+
jarToTarget.put(ops.directJars[i], ops.directTargets[i]);
54+
}
55+
} else {
56+
throw new IllegalArgumentException(
57+
"mismatched size: directJars " + ops.directJars.length + " vs directTargets"
58+
+ ops.directTargets.length);
59+
}
60+
61+
if (ops.indirectJars.length == ops.indirectTargets.length) {
62+
for (int i = 0; i < ops.indirectJars.length; i++) {
63+
indirectJarToTarget.put(ops.indirectJars[i], ops.indirectTargets[i]);
64+
}
65+
} else {
66+
throw new IllegalArgumentException(
67+
"mismatched size: indirectJars " + ops.directJars.length + " vs indirectTargets "
68+
+ ops.directTargets.length);
69+
}
70+
71+
ignoredTargets = Arrays.stream(ops.unusedDepsIgnoredTargets).collect(Collectors.toSet());
72+
directTargets = Arrays.stream(ops.directTargets).collect(Collectors.toSet());
73+
}
74+
75+
private boolean isDependencyTrackingOn() {
76+
return "ast-plus".equals(ops.dependencyTrackingMethod)
77+
&& (!"off".equals(ops.strictDepsMode) || !"off".equals(ops.unusedDependencyCheckerMode));
78+
}
79+
80+
@Override
81+
public void doReport(Position pos, String msg, Severity severity, scala.collection.immutable.List<CodeAction> actions) {
82+
if (msg.startsWith("DT:")) {
83+
if (isDependencyTrackingOn()) {
84+
parseOpenedJar(msg);
85+
}
86+
} else {
87+
if (delegateReporter != null) {
88+
delegateReporter.doReport(pos, msg, severity, List$.MODULE$.<CodeAction>empty());
89+
} else {
90+
super.doReport(pos, msg, severity, List$.MODULE$.<CodeAction>empty());
91+
}
92+
}
93+
}
94+
95+
private void parseOpenedJar(String msg) {
96+
String jar = msg.split(":")[1];
97+
98+
//normalize path separators (scalac passes os-specific path separators.)
99+
jar = jar.replace("\\", "/");
100+
101+
// track only jars from dependency targets
102+
// this should exclude things like rt.jar which come from JDK
103+
if (jarToTarget.containsKey(jar) || indirectJarToTarget.containsKey(jar)) {
104+
usedJars.add(jar);
105+
}
106+
}
107+
108+
public void prepareReport() throws IOException {
109+
Set<String> usedTargets = new HashSet<>();
110+
Set<Dependency> usedDeps = new HashSet<>();
111+
112+
for (String jar : usedJars) {
113+
String target = jarToTarget.get(jar);
114+
115+
if (target == null) {
116+
target = indirectJarToTarget.get(jar);
117+
}
118+
119+
if (target.startsWith("Unknown")) {
120+
target = jarLabel(jar);
121+
}
122+
123+
if (target == null) {
124+
// probably a bug if we get here
125+
continue;
126+
}
127+
128+
Dependency dep = buildDependency(
129+
jar,
130+
target,
131+
astUsedJars.contains(jar) ? Kind.EXPLICIT : Kind.IMPLICIT,
132+
ignoredTargets.contains(target)
133+
);
134+
135+
usedTargets.add(target);
136+
usedDeps.add(dep);
137+
}
138+
139+
Set<Dependency> unusedDeps = new HashSet<>();
140+
for (int i = 0; i < ops.directTargets.length; i++) {
141+
String directTarget = ops.directTargets[i];
142+
if (usedTargets.contains(directTarget)) {
143+
continue;
144+
}
145+
146+
unusedDeps.add(
147+
buildDependency(
148+
ops.directJars[i],
149+
directTarget,
150+
Kind.UNUSED,
151+
ignoredTargets.contains(directTarget) || "off".equals(ops.unusedDependencyCheckerMode)
152+
)
153+
);
154+
}
155+
156+
writeSdepsFile(usedDeps, unusedDeps);
157+
158+
Reporter reporter = this.delegateReporter != null ? this.delegateReporter : this;
159+
reportDeps(usedDeps, unusedDeps, reporter);
160+
}
161+
162+
private Dependency buildDependency(String jar, String target, Kind kind, boolean ignored) {
163+
ScalaDeps.Dependency.Builder dependecyBuilder = ScalaDeps.Dependency.newBuilder();
164+
165+
dependecyBuilder.setKind(kind);
166+
dependecyBuilder.setLabel(target);
167+
dependecyBuilder.setIjarPath(jar);
168+
dependecyBuilder.setPath(guessFullJarPath(jar));
169+
dependecyBuilder.setIgnored(ignored);
170+
171+
return dependecyBuilder.build();
172+
}
173+
174+
private void writeSdepsFile(Collection<Dependency> usedDeps, Collection<Dependency> unusedDeps)
175+
throws IOException {
176+
177+
ScalaDeps.Dependencies.Builder builder = ScalaDeps.Dependencies.newBuilder();
178+
builder.setRuleLabel(ops.currentTarget);
179+
builder.setDependencyTrackingMethod(ops.dependencyTrackingMethod);
180+
builder.addAllDependency(usedDeps);
181+
builder.addAllDependency(unusedDeps);
182+
183+
try (OutputStream outputStream = new BufferedOutputStream(
184+
Files.newOutputStream(Paths.get(ops.scalaDepsFile)))) {
185+
outputStream.write(builder.build().toByteArray());
186+
}
187+
}
188+
189+
private void reportDeps(Collection<Dependency> usedDeps, Collection<Dependency> unusedDeps,
190+
Reporter reporter) {
191+
if (ops.dependencyTrackingMethod.equals("ast-plus")) {
192+
193+
if (!ops.strictDepsMode.equals("off")) {
194+
boolean isWarning = ops.strictDepsMode.equals("warn");
195+
StringBuilder strictDepsReport = new StringBuilder("Missing strict dependencies:\n");
196+
StringBuilder compilerDepsReport = new StringBuilder("Missing compiler dependencies:\n");
197+
int strictDepsCount = 0;
198+
int compilerDepsCount = 0;
199+
for (Dependency dep : usedDeps) {
200+
String depReport = addDepMessage(dep);
201+
if (dep.getIgnored()) {
202+
continue;
203+
}
204+
205+
if (directTargets.contains(dep.getLabel())) {
206+
continue;
207+
}
208+
209+
if (dep.getKind() == Kind.EXPLICIT) {
210+
strictDepsCount++;
211+
strictDepsReport
212+
.append(isWarning ? "warning: " : "error: ")
213+
.append(depReport);
214+
} else {
215+
compilerDepsCount++;
216+
compilerDepsReport
217+
.append(isWarning ? "warning: " : "error: ")
218+
.append(depReport);
219+
}
220+
}
221+
222+
if (strictDepsCount > 0) {
223+
if (ops.strictDepsMode.equals("warn")) {
224+
reporter.warning(NoPosition$.MODULE$, strictDepsReport.toString(), List$.MODULE$.<CodeAction>empty());
225+
} else {
226+
reporter.error(NoPosition$.MODULE$, strictDepsReport.toString(), List$.MODULE$.<CodeAction>empty());
227+
}
228+
}
229+
230+
if (!ops.compilerDepsMode.equals("off") && compilerDepsCount > 0) {
231+
if (ops.compilerDepsMode.equals("warn")) {
232+
reporter.warning(NoPosition$.MODULE$, compilerDepsReport.toString(), List$.MODULE$.<CodeAction>empty());
233+
} else {
234+
reporter.error(NoPosition$.MODULE$, compilerDepsReport.toString(), List$.MODULE$.<CodeAction>empty());
235+
}
236+
}
237+
}
238+
239+
if (!ops.unusedDependencyCheckerMode.equals("off")) {
240+
boolean isWarning = ops.unusedDependencyCheckerMode.equals("warn");
241+
StringBuilder unusedDepsReport = new StringBuilder("Unused dependencies:\n");
242+
int count = 0;
243+
for (Dependency dep : unusedDeps) {
244+
if (dep.getIgnored()) {
245+
continue;
246+
}
247+
count++;
248+
unusedDepsReport
249+
.append(isWarning ? "warning: " : "error: ")
250+
.append(removeDepMessage(dep));
251+
}
252+
if (count > 0) {
253+
if (isWarning) {
254+
reporter.warning(NoPosition$.MODULE$, unusedDepsReport.toString(), List$.MODULE$.<CodeAction>empty());
255+
} else if (ops.unusedDependencyCheckerMode.equals("error")) {
256+
reporter.error(NoPosition$.MODULE$, unusedDepsReport.toString(), List$.MODULE$.<CodeAction>empty());
257+
}
258+
}
259+
}
260+
}
261+
}
262+
263+
private String addDepMessage(Dependency dep) {
264+
String target = dep.getLabel();
265+
String jar = dep.getPath();
266+
267+
String message = "Target '" + target + "' (via jar: ' " + jar + " ') "
268+
+ "is being used by " + ops.currentTarget
269+
+ " but is is not specified as a dependency, please add it to the deps.\n"
270+
+ "You can use the following buildozer command:\n";
271+
String command = "buildozer 'add deps " + target + "' " + ops.currentTarget + "\n";
272+
return message + command;
273+
}
274+
275+
private String removeDepMessage(Dependency dep) {
276+
String target = dep.getLabel();
277+
String jar = dep.getPath();
278+
279+
String message = "Target '" + target + "' (via jar: ' " + jar + " ') "
280+
+ "is specified as a dependency to " + ops.currentTarget
281+
+ " but isn't used, please remove it from the deps.\n"
282+
+ "You can use the following buildozer command:\n";
283+
String command = "buildozer 'remove deps " + target + "' " + ops.currentTarget + "\n";
284+
285+
return message + command;
286+
}
287+
288+
private String guessFullJarPath(String jar) {
289+
if (jar.endsWith(IJAR_JAR_SUFFIX)) {
290+
return stripIjarSuffix(jar, IJAR_JAR_SUFFIX);
291+
} else if (jar.endsWith(HJAR_JAR_SUFFIX)) {
292+
return stripIjarSuffix(jar, HJAR_JAR_SUFFIX);
293+
} else {
294+
return jar;
295+
}
296+
}
297+
298+
private static String stripIjarSuffix(String jar, String suffix) {
299+
return jar.substring(0, jar.length() - suffix.length()) + ".jar";
300+
}
301+
302+
private String jarLabel(String path) throws IOException {
303+
try (JarFile jar = new JarFile(path)) {
304+
return jar.getManifest().getMainAttributes().getValue("Target-Label");
305+
}
306+
}
307+
308+
public void registerAstUsedJars(Set<String> jars) {
309+
astUsedJars = jars;
310+
}
311+
312+
public void writeDiagnostics(String diagnosticsFile) throws IOException {
313+
if (delegateReporter == null) {
314+
return;
315+
}
316+
317+
ProtoReporter protoReporter = (ProtoReporter) delegateReporter;
318+
protoReporter.writeTo(Paths.get(diagnosticsFile));
319+
}
320+
}

src/java/io/bazel/rulesscala/scalac/reporter/BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ load("@io_bazel_rules_scala_config//:config.bzl", "SCALA_MAJOR_VERSION")
55
java_library(
66
name = "reporter",
77
srcs = [
8-
"DepsTrackingReporter.java",
8+
"//src/java/io/bazel/rulesscala/scalac/deps_tracking_reporter",
99
"ProtoReporter.java",
1010
] if SCALA_MAJOR_VERSION.startswith("2") else ["PlaceholderForEmptyScala3Lib.java"],
1111
visibility = ["//visibility:public"],

0 commit comments

Comments
 (0)