Skip to content

Commit e730cf4

Browse files
Add check for JAVA 9 (#3294)
* Add check for JAVA 9 Currently Gradle cannot work with JAVA 9, so detect if it has been used and break the build for Android. Also the check will print warning when `tns doctor` is called. Also update submodule, where the following change is applied: Fix detection of Javac version The command `javac -version` prints result to stderr when JAVA 8 is used and to stdout when JAVA 9 is used. Current check in CLI uses the stderr output, so when JAVA 9 is installed it fails to detect the correct version. In order to support both JAVA 8 and JAVA 9, capture both stdout and stderr and get the version from there. Also remove unneeded check for Java version - we care about JAVA Compiler, which is included in JDK. * Handle case when Javac version is a single number (9 for example) In some cases javac version is a single number, for example 9. In this case our validation fails to detect the correct version and to check if we support this version. In order to resolve this issue, use the `appendZeroesToVersion` method in order to make the versin semver valid. Change the return type of `validateJavacVersion` method - it does not require to return a Promise. Add unit tests for `validateJavacVersion` method.
1 parent c707331 commit e730cf4

7 files changed

+130
-11
lines changed

lib/android-tools-info.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as path from "path";
22
import * as semver from "semver";
33
import { EOL } from "os";
44
import { cache } from "./common/decorators";
5+
import { appendZeroesToVersion } from './common/helpers';
56

67
export class AndroidToolsInfo implements IAndroidToolsInfo {
78
private static ANDROID_TARGET_PREFIX = "android";
@@ -10,6 +11,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
1011
private static REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23";
1112
private static VERSION_REGEX = /((\d+\.){2}\d+)/;
1213
private static MIN_JAVA_VERSION = "1.8.0";
14+
private static MAX_JAVA_VERSION = "1.9.0";
1315

1416
private showWarningsAsErrors: boolean;
1517
private toolsInfo: IAndroidToolsInfoData;
@@ -101,7 +103,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
101103
return detectedErrors || !isAndroidHomeValid;
102104
}
103105

104-
public async validateJavacVersion(installedJavaVersion: string, options?: { showWarningsAsErrors: boolean }): Promise<boolean> {
106+
public validateJavacVersion(installedJavacVersion: string, options?: { showWarningsAsErrors: boolean }): boolean {
105107
let hasProblemWithJavaVersion = false;
106108
if (options) {
107109
this.showWarningsAsErrors = options.showWarningsAsErrors;
@@ -110,11 +112,16 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
110112
const additionalMessage = "You will not be able to build your projects for Android." + EOL
111113
+ "To be able to build for Android, verify that you have installed The Java Development Kit (JDK) and configured it according to system requirements as" + EOL +
112114
" described in " + this.$staticConfig.SYS_REQUIREMENTS_LINK;
113-
const matchingVersion = (installedJavaVersion || "").match(AndroidToolsInfo.VERSION_REGEX);
114-
if (matchingVersion && matchingVersion[1]) {
115-
if (semver.lt(matchingVersion[1], AndroidToolsInfo.MIN_JAVA_VERSION)) {
115+
116+
const matchingVersion = appendZeroesToVersion(installedJavacVersion || "", 3).match(AndroidToolsInfo.VERSION_REGEX);
117+
const installedJavaCompilerVersion = matchingVersion && matchingVersion[1];
118+
if (installedJavaCompilerVersion) {
119+
if (semver.lt(installedJavaCompilerVersion, AndroidToolsInfo.MIN_JAVA_VERSION)) {
120+
hasProblemWithJavaVersion = true;
121+
this.printMessage(`Javac version ${installedJavacVersion} is not supported. You have to install at least ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, additionalMessage);
122+
} else if (semver.gte(installedJavaCompilerVersion, AndroidToolsInfo.MAX_JAVA_VERSION)) {
116123
hasProblemWithJavaVersion = true;
117-
this.printMessage(`Javac version ${installedJavaVersion} is not supported. You have to install at least ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, additionalMessage);
124+
this.printMessage(`Javac version ${installedJavacVersion} is not supported. You have to install version ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, additionalMessage);
118125
}
119126
} else {
120127
hasProblemWithJavaVersion = true;

lib/declarations.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ interface IAndroidToolsInfo {
490490
* @param {any} options Defines if the warning messages should treated as error.
491491
* @return {boolean} True if there are detected issues, false otherwise.
492492
*/
493-
validateJavacVersion(installedJavaVersion: string, options?: { showWarningsAsErrors: boolean }): Promise<boolean>;
493+
validateJavacVersion(installedJavaVersion: string, options?: { showWarningsAsErrors: boolean }): boolean;
494494

495495
/**
496496
* Validates if ANDROID_HOME environment variable is set correctly.

lib/services/android-project-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
138138

139139
const javaCompilerVersion = await this.$sysInfo.getJavaCompilerVersion();
140140

141-
await this.$androidToolsInfo.validateJavacVersion(javaCompilerVersion, { showWarningsAsErrors: true });
141+
this.$androidToolsInfo.validateJavacVersion(javaCompilerVersion, { showWarningsAsErrors: true });
142142

143143
await this.$androidToolsInfo.validateInfo({ showWarningsAsErrors: true, validateTargetSdk: true });
144144
}

lib/services/doctor-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ class DoctorService implements IDoctorService {
104104
}
105105

106106
const androidToolsIssues = this.$androidToolsInfo.validateInfo();
107-
const javaVersionIssue = await this.$androidToolsInfo.validateJavacVersion(sysInfo.javacVersion);
107+
const javaCompilerVersionIssue = this.$androidToolsInfo.validateJavacVersion(sysInfo.javacVersion);
108108
const pythonIssues = await this.validatePythonPackages();
109-
const doctorResult = result || androidToolsIssues || javaVersionIssue || pythonIssues;
109+
const doctorResult = result || androidToolsIssues || javaCompilerVersionIssue || pythonIssues;
110110

111111
if (!configOptions || configOptions.trackResult) {
112112
await this.$analyticsService.track("DoctorEnvironmentSetup", doctorResult ? "incorrect" : "correct");

test/android-tools-info.ts

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { Yok } from "../lib/common/yok";
2+
import { AndroidToolsInfo } from "../lib/android-tools-info";
3+
import { EOL } from "os";
4+
import { format } from "util";
5+
import { assert } from "chai";
6+
7+
interface ITestData {
8+
javacVersion: string;
9+
expectedResult: boolean;
10+
warnings?: string[];
11+
}
12+
13+
describe("androidToolsInfo", () => {
14+
let loggedWarnings: string[] = [];
15+
let loggedMarkdownMessages: string[] = [];
16+
const sysRequirementsLink = "";
17+
18+
const additionalMsg = "You will not be able to build your projects for Android." + EOL
19+
+ "To be able to build for Android, verify that you have installed The Java Development Kit (JDK) and configured it according to system requirements as" + EOL +
20+
" described in " + sysRequirementsLink;
21+
22+
beforeEach(() => {
23+
loggedWarnings = [];
24+
loggedMarkdownMessages = [];
25+
});
26+
27+
const createTestInjector = (): IInjector => {
28+
const testInjector = new Yok();
29+
testInjector.register("childProcess", {});
30+
testInjector.register("errors", {
31+
failWithoutHelp: (message: string, ...args: any[]): any => {
32+
const loggedError = format(message, args);
33+
throw new Error(loggedError);
34+
}
35+
});
36+
testInjector.register("fs", {});
37+
testInjector.register("hostInfo", {});
38+
testInjector.register("logger", {
39+
warn: (...args: string[]): void => {
40+
loggedWarnings.push(format.apply(null, args));
41+
},
42+
43+
printMarkdown: (...args: string[]): void => {
44+
loggedMarkdownMessages.push(format.apply(null, args));
45+
}
46+
});
47+
testInjector.register("options", {});
48+
testInjector.register("staticConfig", {
49+
SYS_REQUIREMENTS_LINK: sysRequirementsLink
50+
});
51+
return testInjector;
52+
};
53+
54+
describe("validateJavacVersion", () => {
55+
const testData: ITestData[] = [
56+
{
57+
javacVersion: "1.8.0",
58+
expectedResult: false
59+
},
60+
{
61+
javacVersion: "1.8.0_152",
62+
expectedResult: false
63+
},
64+
{
65+
javacVersion: "9",
66+
expectedResult: true,
67+
warnings: ["Javac version 9 is not supported. You have to install version 1.8.0."]
68+
},
69+
{
70+
javacVersion: "9.0.1",
71+
expectedResult: true,
72+
warnings: ["Javac version 9.0.1 is not supported. You have to install version 1.8.0."]
73+
},
74+
{
75+
javacVersion: "1.7.0",
76+
expectedResult: true,
77+
warnings: ["Javac version 1.7.0 is not supported. You have to install at least 1.8.0."]
78+
},
79+
{
80+
javacVersion: "1.7.0_132",
81+
expectedResult: true,
82+
warnings: ["Javac version 1.7.0_132 is not supported. You have to install at least 1.8.0."]
83+
},
84+
{
85+
javacVersion: null,
86+
expectedResult: true,
87+
warnings: ["Error executing command 'javac'. Make sure you have installed The Java Development Kit (JDK) and set JAVA_HOME environment variable."]
88+
}
89+
];
90+
91+
_.each(testData, ({ javacVersion, expectedResult, warnings }) => {
92+
it(`returns ${expectedResult} when version is ${javacVersion}`, () => {
93+
const testInjector = createTestInjector();
94+
const androidToolsInfo = testInjector.resolve<IAndroidToolsInfo>(AndroidToolsInfo);
95+
assert.deepEqual(androidToolsInfo.validateJavacVersion(javacVersion), expectedResult);
96+
if (warnings && warnings.length) {
97+
assert.deepEqual(loggedWarnings, warnings);
98+
assert.deepEqual(loggedMarkdownMessages, [additionalMsg]);
99+
} else {
100+
assert.equal(loggedWarnings.length, 0);
101+
assert.equal(loggedMarkdownMessages.length, 0);
102+
}
103+
});
104+
});
105+
106+
it("throws error when passing showWarningsAsErrors to true and javac is not installed", () => {
107+
const testInjector = createTestInjector();
108+
const androidToolsInfo = testInjector.resolve<IAndroidToolsInfo>(AndroidToolsInfo);
109+
assert.throws(() => androidToolsInfo.validateJavacVersion(null, { showWarningsAsErrors: true }), "Error executing command 'javac'. Make sure you have installed The Java Development Kit (JDK) and set JAVA_HOME environment variable.");
110+
});
111+
});
112+
});

test/stubs.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ export class AndroidToolsInfoStub implements IAndroidToolsInfo {
532532
return true;
533533
}
534534

535-
public async validateJavacVersion(installedJavaVersion: string, options?: { showWarningsAsErrors: boolean }): Promise<boolean> {
535+
public validateJavacVersion(installedJavaVersion: string, options?: { showWarningsAsErrors: boolean }): boolean {
536536
return true;
537537
}
538538

0 commit comments

Comments
 (0)