Skip to content

Commit 66d7ec2

Browse files
committed
feat: add target validation and more tools info
1 parent 6ba14a3 commit 66d7ec2

File tree

7 files changed

+134
-56
lines changed

7 files changed

+134
-56
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,5 @@ test-reports.xml
6464
*.js
6565
*.js.map
6666
/lib/.d.ts
67-
67+
.d.ts
6868
!/*.js

lib/android-tools-info.ts

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import { Helpers } from './helpers';
66
import { EOL } from "os";
77
import * as semver from "semver";
88
import * as path from "path";
9+
import * as _ from "lodash";
910

1011
export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
11-
private static ANDROID_TARGET_PREFIX = "android";
12-
private static SUPPORTED_TARGETS = [
12+
public readonly ANDROID_TARGET_PREFIX = "android";
13+
public readonly SUPPORTED_TARGETS = [
1314
"android-17",
1415
"android-18",
1516
"android-19",
@@ -22,13 +23,15 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
2223
"android-27",
2324
"android-28",
2425
];
25-
private static MIN_REQUIRED_COMPILE_TARGET = 28;
26-
private static REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23";
27-
private static VERSION_REGEX = /((\d+\.){2}\d+)/;
26+
public readonly MIN_REQUIRED_COMPILE_TARGET = 28;
27+
public readonly REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23";
28+
public readonly VERSION_REGEX = /((\d+\.){2}\d+)/;
2829
private static MIN_JAVA_VERSION = "1.8.0";
2930

3031
private toolsInfo: NativeScriptDoctor.IAndroidToolsInfoData;
31-
private androidHome = process.env["ANDROID_HOME"];
32+
public get androidHome(): string {
33+
return process.env["ANDROID_HOME"];
34+
}
3235
private pathToEmulatorExecutable: string;
3336

3437
constructor(private childProcess: ChildProcess,
@@ -40,8 +43,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
4043
if (!this.toolsInfo) {
4144
const infoData: NativeScriptDoctor.IAndroidToolsInfoData = Object.create(null);
4245
infoData.androidHomeEnvVar = this.androidHome;
43-
infoData.compileSdkVersion = this.getCompileSdk();
46+
infoData.installedTargets = this.getInstalledTargets();
47+
infoData.latestValidAndroidTarget = this.getLatestValidAndroidTarget(infoData.installedTargets);
48+
infoData.compileSdkVersion = this.getCompileSdk(infoData.latestValidAndroidTarget);
4449
infoData.buildToolsVersion = this.getBuildToolsVersion();
50+
infoData.maxSupportedSdkVersion = this.getMaxSupportedVersion();
4551

4652
this.toolsInfo = infoData;
4753
}
@@ -55,7 +61,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
5561
const isAndroidHomeValid = this.isAndroidHomeValid();
5662
if (!toolsInfoData.compileSdkVersion) {
5763
errors.push({
58-
warning: `Cannot find a compatible Android SDK for compilation. To be able to build for Android, install Android SDK ${AndroidToolsInfo.MIN_REQUIRED_COMPILE_TARGET} or later.`,
64+
warning: `Cannot find a compatible Android SDK for compilation. To be able to build for Android, install Android SDK ${this.MIN_REQUIRED_COMPILE_TARGET} or later.`,
5965
additionalInformation: `Run \`\$ ${this.getPathToSdkManagementTool()}\` to manage your Android SDK versions.`,
6066
platforms: [Constants.ANDROID_PLATFORM_NAME]
6167
});
@@ -93,7 +99,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
9399
+ "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 +
94100
" described in " + this.getSystemRequirementsLink();
95101

96-
const matchingVersion = this.helpers.appendZeroesToVersion(installedJavaCompilerVersion || "", 3).match(AndroidToolsInfo.VERSION_REGEX);
102+
const matchingVersion = this.helpers.appendZeroesToVersion(installedJavaCompilerVersion || "", 3).match(this.VERSION_REGEX);
97103
const installedJavaCompilerSemverVersion = matchingVersion && matchingVersion[1];
98104
if (installedJavaCompilerSemverVersion) {
99105
let warning: string = null;
@@ -145,7 +151,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
145151

146152
public async getPathToAdbFromAndroidHome(): Promise<string> {
147153
if (this.androidHome) {
148-
let pathToAdb = path.join(this.androidHome, "platform-tools", "adb");
154+
const pathToAdb = path.join(this.androidHome, "platform-tools", "adb");
149155
try {
150156
await this.childProcess.execFile(pathToAdb, ["help"]);
151157
return pathToAdb;
@@ -179,6 +185,43 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
179185
return errors;
180186
}
181187

188+
public validateMinSupportedTargetSdk(targetSdk: number): NativeScriptDoctor.IWarning[] {
189+
const errors: NativeScriptDoctor.IWarning[] = [];
190+
const newTarget = `${this.ANDROID_TARGET_PREFIX}-${targetSdk}`;
191+
const targetSupported = _.includes(this.SUPPORTED_TARGETS, newTarget);
192+
193+
if (!_.includes(this.SUPPORTED_TARGETS, newTarget)) {
194+
const supportedVersions = this.SUPPORTED_TARGETS.sort();
195+
const minSupportedVersion = this.parseAndroidSdkString(_.first(supportedVersions));
196+
197+
if (!targetSupported && targetSdk && (targetSdk < minSupportedVersion)) {
198+
errors.push({
199+
warning:`The selected Android target SDK ${newTarget} is not supported. You must target ${minSupportedVersion} or later.`,
200+
additionalInformation: "",
201+
platforms: [Constants.ANDROID_PLATFORM_NAME]
202+
});
203+
}
204+
}
205+
206+
return [];
207+
}
208+
209+
public validataMaxSupportedTargetSdk(targetSdk: number): NativeScriptDoctor.IWarning[] {
210+
const errors: NativeScriptDoctor.IWarning[] = [];
211+
const newTarget = `${this.ANDROID_TARGET_PREFIX}-${targetSdk}`;
212+
const targetSupported = _.includes(this.SUPPORTED_TARGETS, newTarget);
213+
214+
if (!targetSupported && !targetSdk || targetSdk > this.getMaxSupportedVersion()) {
215+
errors.push({
216+
warning:`Support for the selected Android target SDK ${newTarget} is not verified. Your Android app might not work as expected.`,
217+
additionalInformation: "",
218+
platforms: [Constants.ANDROID_PLATFORM_NAME]
219+
});
220+
}
221+
222+
return errors;
223+
}
224+
182225
public getPathToEmulatorExecutable(): string {
183226
if (!this.pathToEmulatorExecutable) {
184227
const emulatorExecutableName = "emulator";
@@ -222,12 +265,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
222265
return sdkManagementToolPath;
223266
}
224267

225-
private getCompileSdk(): number {
226-
let latestValidAndroidTarget = this.getLatestValidAndroidTarget();
268+
private getCompileSdk(latestValidAndroidTarget: string): number {
227269
if (latestValidAndroidTarget) {
228-
let integerVersion = this.parseAndroidSdkString(latestValidAndroidTarget);
270+
const integerVersion = this.parseAndroidSdkString(latestValidAndroidTarget);
229271

230-
if (integerVersion && integerVersion >= AndroidToolsInfo.MIN_REQUIRED_COMPILE_TARGET) {
272+
if (integerVersion && integerVersion >= this.MIN_REQUIRED_COMPILE_TARGET) {
231273
return integerVersion;
232274
}
233275
}
@@ -236,11 +278,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
236278
private getMatchingDir(pathToDir: string, versionRange: string): string {
237279
let selectedVersion: string;
238280
if (this.fs.exists(pathToDir)) {
239-
let subDirs = this.fs.readDirectory(pathToDir);
281+
const subDirs = this.fs.readDirectory(pathToDir);
240282

241-
let subDirsVersions = subDirs
283+
const subDirsVersions = subDirs
242284
.map(dirName => {
243-
let dirNameGroups = dirName.match(AndroidToolsInfo.VERSION_REGEX);
285+
const dirNameGroups = dirName.match(this.VERSION_REGEX);
244286
if (dirNameGroups) {
245287
return dirNameGroups[1];
246288
}
@@ -249,7 +291,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
249291
})
250292
.filter(dirName => !!dirName);
251293

252-
let version = semver.maxSatisfying(subDirsVersions, versionRange);
294+
const version = semver.maxSatisfying(subDirsVersions, versionRange);
253295
if (version) {
254296
selectedVersion = subDirs.find(dir => dir.indexOf(version) !== -1);
255297
}
@@ -259,36 +301,26 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
259301
}
260302

261303
private getBuildToolsRange(): string {
262-
return `${AndroidToolsInfo.REQUIRED_BUILD_TOOLS_RANGE_PREFIX} <=${this.getMaxSupportedVersion()}`;
304+
return `${this.REQUIRED_BUILD_TOOLS_RANGE_PREFIX} <=${this.getMaxSupportedVersion()}`;
263305
}
264306

265307
private getBuildToolsVersion(): string {
266308
let buildToolsVersion: string;
267309
if (this.androidHome) {
268-
let pathToBuildTools = path.join(this.androidHome, "build-tools");
269-
let buildToolsRange = this.getBuildToolsRange();
310+
const pathToBuildTools = path.join(this.androidHome, "build-tools");
311+
const buildToolsRange = this.getBuildToolsRange();
270312
buildToolsVersion = this.getMatchingDir(pathToBuildTools, buildToolsRange);
271313
}
272314

273315
return buildToolsVersion;
274316
}
275317

276-
private getLatestValidAndroidTarget(): string {
277-
const installedTargets = this.getInstalledTargets();
278-
let latestValidAndroidTarget: string;
279-
const sortedAndroidToolsInfo = AndroidToolsInfo.SUPPORTED_TARGETS.sort();
280-
281-
sortedAndroidToolsInfo.forEach(s => {
282-
if (installedTargets.indexOf(s) >= 0) {
283-
latestValidAndroidTarget = s;
284-
}
285-
});
286-
287-
return latestValidAndroidTarget;
318+
private getLatestValidAndroidTarget(installedTargets: string[]): string {
319+
return _.findLast(this.SUPPORTED_TARGETS.sort(), supportedTarget => _.includes(installedTargets, supportedTarget));
288320
}
289321

290322
private parseAndroidSdkString(androidSdkString: string): number {
291-
return parseInt(androidSdkString.replace(`${AndroidToolsInfo.ANDROID_TARGET_PREFIX}-`, ""));
323+
return parseInt(androidSdkString.replace(`${this.ANDROID_TARGET_PREFIX}-`, ""));
292324
}
293325

294326
private getInstalledTargets(): string[] {
@@ -305,7 +337,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
305337
}
306338

307339
private getMaxSupportedVersion(): number {
308-
return this.parseAndroidSdkString(AndroidToolsInfo.SUPPORTED_TARGETS.sort()[AndroidToolsInfo.SUPPORTED_TARGETS.length - 1]);
340+
return this.parseAndroidSdkString(this.SUPPORTED_TARGETS.sort()[this.SUPPORTED_TARGETS.length - 1]);
309341
}
310342

311343
private getSystemRequirementsLink(): string {

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"homepage": "https://github.com/NativeScript/nativescript-doctor#readme",
2525
"devDependencies": {
2626
"@types/chai": "4.1.0",
27+
"@types/lodash": "4.14.123",
2728
"@types/mocha": "2.2.32",
2829
"@types/rimraf": "2.0.2",
2930
"@types/semver": "5.5.0",
@@ -36,12 +37,14 @@
3637
"grunt-contrib-watch": "1.1.0",
3738
"grunt-shell": "2.0.0",
3839
"grunt-ts": "6.0.0-beta.21",
39-
"grunt-tslint": "3.3.0",
40+
"grunt-tslint": "5.0.2",
4041
"istanbul": "0.4.5",
42+
"lodash": "4.17.11",
4143
"mocha": "5.2.0",
4244
"rimraf": "2.5.4",
43-
"tslint": "3.15.1",
44-
"typescript": "2.0.3"
45+
"tslint": "5.14.0",
46+
"tslint-microsoft-contrib": "6.1.0",
47+
"typescript": "3.3.4000"
4548
},
4649
"dependencies": {
4750
"osenv": "0.1.3",

test/android-local-build-requirements.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ describe("androidLocalBuildRequirements", () => {
1313
describe("checkRequirements", () => {
1414
const setupTestCase = (results: ITestCaseData): AndroidLocalBuildRequirements => {
1515
const androidToolsInfo: NativeScriptDoctor.IAndroidToolsInfo = {
16+
ANDROID_TARGET_PREFIX: "",
17+
androidHome: "",
1618
validateInfo: (): NativeScriptDoctor.IWarning[] => results.validateInfo || [],
1719
validateAndroidHomeEnvVariable: (): NativeScriptDoctor.IWarning[] => [],
1820
getToolsInfo: (): NativeScriptDoctor.IAndroidToolsInfoData => null,
1921
validateJavacVersion: (installedJavaVersion: string, projectDir?: string, runtimeVersion?: string): NativeScriptDoctor.IWarning[] => results.validateJavacVersion || [],
2022
getPathToAdbFromAndroidHome: async (): Promise<string> => undefined,
21-
getPathToEmulatorExecutable: (): string => undefined
23+
getPathToEmulatorExecutable: (): string => undefined,
24+
validateMinSupportedTargetSdk: (): NativeScriptDoctor.IWarning[] => [],
25+
validataMaxSupportedTargetSdk: (): NativeScriptDoctor.IWarning[] => []
2226
};
2327

2428
const sysInfo: NativeScriptDoctor.ISysInfo = {

test/sys-info.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ interface IFileSystemMockOptions {
5757
}
5858

5959
const androidToolsInfo: NativeScriptDoctor.IAndroidToolsInfo = {
60+
ANDROID_TARGET_PREFIX: "",
61+
androidHome: "",
6062
getPathToAdbFromAndroidHome: async () => {
6163
return "adb";
6264
},
@@ -74,7 +76,9 @@ const androidToolsInfo: NativeScriptDoctor.IAndroidToolsInfo = {
7476
},
7577
validateJavacVersion: (): any[] => {
7678
return [];
77-
}
79+
},
80+
validateMinSupportedTargetSdk: (): NativeScriptDoctor.IWarning[] => [],
81+
validataMaxSupportedTargetSdk: (): NativeScriptDoctor.IWarning[] => []
7882
};
7983

8084
function createChildProcessResults(childProcessResult: IChildProcessResults): IDictionary<IChildProcessResultDescription> {

tslint.json

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,74 @@
11
{
2+
"rulesDirectory": "node_modules/tslint-microsoft-contrib",
23
"rules": {
34
"class-name": true,
45
"curly": true,
56
"eofline": true,
6-
"indent": true,
7+
"mocha-avoid-only": true,
8+
"indent": [
9+
true,
10+
"tabs"
11+
],
712
"interface-name": true,
813
"jsdoc-format": true,
9-
"max-line-length": [false, 140],
14+
"max-line-length": [
15+
false,
16+
140
17+
],
18+
"prefer-const": true,
1019
"no-consecutive-blank-lines": true,
1120
"no-construct": true,
1221
"no-debugger": true,
13-
"no-duplicate-key": true,
1422
"no-duplicate-variable": true,
1523
"no-shadowed-variable": true,
1624
"no-empty": true,
1725
"no-eval": true,
1826
"no-switch-case-fall-through": true,
1927
"no-trailing-whitespace": true,
20-
"no-unreachable": true,
2128
"no-unused-expression": true,
22-
"no-unused-variable": true,
2329
"no-use-before-declare": true,
2430
"no-var-keyword": true,
2531
"no-var-requires": false,
2632
"one-line": [
2733
true,
28-
"check-open-brace",
2934
"check-catch",
30-
"check-else"
35+
"check-finally",
36+
"check-else",
37+
"check-open-brace",
38+
"check-whitespace"
39+
],
40+
"no-floating-promises": true,
41+
"quotemark": [
42+
false,
43+
"double"
3144
],
32-
"quotemark": [false, "double"],
3345
"semicolon": true,
46+
"space-before-function-paren": false,
3447
"switch-default": false,
35-
"triple-equals": [true, "allow-null-check"],
36-
"use-strict": true,
37-
"variable-name": [false, "allow-leading-underscore"],
38-
"whitespace": [
48+
"trailing-comma": [
3949
false,
50+
{
51+
"multiline": "always",
52+
"singleline": "always"
53+
}
54+
],
55+
"triple-equals": [
56+
true,
57+
"allow-null-check"
58+
],
59+
"use-isnan": true,
60+
"variable-name": [
61+
true,
62+
"ban-keywords",
63+
"allow-leading-underscore"
64+
],
65+
"whitespace": [
66+
true,
4067
"check-branch",
4168
"check-decl",
4269
"check-operator",
4370
"check-module",
44-
"check-separator",
45-
"check-type",
46-
"check-typecast"
71+
"check-separator"
4772
]
4873
}
4974
}

0 commit comments

Comments
 (0)