@pi-r/android 0.11.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,18 @@
1
1
  "use strict";
2
- const path = require("node:path");
3
- const fs = require("node:fs");
4
- const Document = require("@e-mc/document");
5
- const types_1 = require("@e-mc/types");
6
- const util_1 = require("@e-mc/document/util");
7
- const REGEXP_SEMVER = /^((\s*,\s*)?[([\]]((\s*,\s*)?\d+\.\d+(\s*,\s*)?)+[)\][])+$/;
2
+
3
+ const path = require('node:path');
4
+ const fs = require('node:fs');
5
+ const Document = require('@e-mc/document');
6
+ const { escapePattern, isArray, isString } = require('@e-mc/types');
7
+ const { getIndent, getNewline, spliceString, trimQuote, wrapQuote } = require('@e-mc/document/util');
8
+ const REGEXP_SEMVER = /^((\s*,\s*)?[([\]]((\s*,\s*)?\d+\.\d+(\s*,\s*)?)+[)[\]])+$/;
8
9
  const REGEXP_DEPENDENCIES = /dependencies\s+\{((?:{[^{]*{|{[^}]*}|}[^}]*}|\\}*?|[^{}+])+)\}/;
9
10
  const REGEXP_DEPENDENCY = /([ \t]*)([A-Za-z_$][\w$]*)(?:\s*\(?\s*(?:module\(?\s*)?["']([^"']+)["']\s*\)?|\s+((?:\s*(?:group|name|version)\s*:\s*(?:"(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+')\s*,?){3}))?/gd;
10
11
  const REGEXP_DEPENDENCY_KOTLIN = /([ \t]*)([A-Za-z_$][\w$]*)\((?:\s*(?:(?:module\(\s*)?"([^"]+)"|((?:\s*(?:group|name|version)\s*=\s*"(?:[^"]|(?<=\\)")+"\s*,?){3}))\s*\))?/gd;
11
12
  const REGEXP_LIBRARY = /([ \t]*)implementation\s+(?:(project|files)\s*\(\s*("(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+')\s*\)|(fileTree)\s*\(\s*((?:\s*(?:dir|include)\s*:\s*(?:"(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+'|\[[^\]]+\])\s*,?){2})\s*\))[ \t\r]*\n/gd;
12
13
  const REGEXP_LIBRARY_KOTLIN = /([ \t]*)implementation\(\s*(?:(project|files)\(\s*"(.+)"\s*\)|(fileTree)\(\s*mapOf\(((?:\s*"(?:dir|include)"\s+to\s+(?:"(?:[^"]|(?<=\\)")+"|listOf\([^)]+\))\s*,?){2})\)\s*\))\s*\)[ \t\r]*\n/gd;
13
- const REGEXP_VERSIONS = /([^\s]+)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{(?:\s*(?:require|strictly|prefer|reject(?:All)?)\s*=\s*(?:"[^"]+"|'[^']+')\s*,?)+\s*\}))/g;
14
- const REGEXP_VERSIONS_LIB = /([^\s]+)\s*=\s*(?:\{\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{[^}]+\}))\s*,\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{[^}]+\}))(?:\s*,\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)')|(\{[^}]+\}))?\s*\}|(?:"([^:]+:[^"]+)"|'([^:]+:[^']+)'))/gd;
14
+ const REGEXP_VERSIONS = /(\S+)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{(?:\s*(?:require|strictly|prefer|reject(?:All)?)\s*=\s*(?:"[^"]+"|'[^']+')\s*,?)+\s*\}))/g;
15
+ const REGEXP_VERSIONS_LIB = /(\S+)\s*=\s*(?:\{\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{[^}]+\}))\s*,\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{[^}]+\}))(?:\s*,\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)')|(\{[^}]+\}))?\s*\}|(?:"([^:]+:[^"]+)"|'([^:]+:[^']+)'))/gd;
15
16
  function isUpgrade(version, pending) {
16
17
  if (isSemVer(pending)) {
17
18
  return true;
@@ -29,7 +30,7 @@ function isUpgrade(version, pending) {
29
30
  return true;
30
31
  }
31
32
  if (isNaN(b) || b < a) {
32
- break;
33
+ return false;
33
34
  }
34
35
  }
35
36
  }
@@ -90,15 +91,21 @@ function writeMethod(kotlin, named, item, args = '', prefix = 'implementation')
90
91
  else {
91
92
  dependency = item.slice(0, 3).join(':');
92
93
  if (dependency.endsWith(':')) {
93
- dependency = dependency.substring(0, dependency.length - 1);
94
+ dependency = dependency.slice(0, -1);
94
95
  }
95
96
  dependency = kotlin ? `("${dependency}")` : ` '${dependency}'`;
96
97
  }
97
98
  return prefix + dependency;
98
99
  }
100
+ function valueFor(name, value, kotlin, quote = false) {
101
+ value = value.toString();
102
+ const q = quote ? kotlin && !value.includes('"') || value.includes("'") ? '"' : "'" : '';
103
+ return `${name} ${kotlin ? '= ' : ''}${q + value + q}`;
104
+ }
99
105
  const isLatest = (value) => value === '' || value.startsWith('latest.');
100
106
  const isSemVer = (value) => isLatest(value) || REGEXP_SEMVER.test(value);
101
- const writeOutput = (match, source, value) => (0, util_1.spliceString)(source, match.index, match.index + match[0].length, value);
107
+ const updateOpts = (updateOnly = false) => ({ upgrade: true, updateOnly });
108
+ const writeOutput = (match, source, value) => spliceString(source, match.index, match.index + match[0].length, value);
102
109
  const toCamelCase = (value) => value.replace(/-([a-z])/gi, (...capture) => capture[1].toUpperCase());
103
110
  function finalize(instance) {
104
111
  const { profileable, dependencies, libraries, dataBinding, jvmToolchain, versionName, versionCode, namespace, applicationId, mainParentDir } = instance.config;
@@ -108,8 +115,9 @@ function finalize(instance) {
108
115
  let { localUri, source, existing, kotlin = false, language } = instance.findTemplate(path.join(this.baseDirectory, mainParentDir), "build.gradle", { detect: instance.detect(this), languageOf: 'gradle' });
109
116
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
110
117
  const javaVersion = instance.config.javaVersion;
111
- let jvmTarget, modified = false;
118
+ const targetAPI = instance.targetAPI;
112
119
  const upgrade = javaVersion > 0;
120
+ let modified = false;
113
121
  const setModified = (output) => {
114
122
  if (output !== source) {
115
123
  source = output;
@@ -118,13 +126,13 @@ function finalize(instance) {
118
126
  };
119
127
  const setDependencies = (match, output) => {
120
128
  if (modified || !existing) {
121
- setModified((0, util_1.spliceString)(source, match.index, match.index + match[0].length, `dependencies {${output}}`));
129
+ setModified(spliceString(source, match.index, match.index + match[0].length, `dependencies {${output}}`));
122
130
  }
123
131
  };
124
132
  if (dependencies) {
125
133
  const { dependencyScopes, versionCatalog } = instance.config;
126
- let mavenData;
127
- const hasScope = (value) => (0, types_1.isArray)(dependencyScopes) && dependencyScopes.includes(value) || dependencyScopes === value;
134
+ let mavenData = null;
135
+ const hasScope = (value) => isArray(dependencyScopes) && dependencyScopes.includes(value) || dependencyScopes === value;
128
136
  const snapshot = dependencyScopes === 1 || hasScope('snapshot');
129
137
  const constraints = hasScope('constraints');
130
138
  const checkVersion = (item, version, value) => !value && version.startsWith('{') && version.endsWith('}') ? false : snapshot || constraints && !item[2] || (version.length > 0 && !version.startsWith('$') || !kotlin && !!value?.includes("'")) && isUpgrade(version, item[2]);
@@ -148,63 +156,62 @@ function finalize(instance) {
148
156
  for (const item of items) {
149
157
  const [gId, id] = item;
150
158
  const target = mavenData[gId]?.find(group => id === group.artifactId);
151
- if (!target) {
152
- continue;
153
- }
154
- if (target.dependencies) {
155
- let found = false;
156
- for (const { groupId, artifactId, version, scope } of target.dependencies) {
157
- if (scope && (dependencyScopes === true || dependencyScopes === 1 || hasScope(scope))) {
158
- let type = -1;
159
- switch (scope) {
160
- case 'compile':
161
- type = 0;
162
- break;
163
- case 'provided':
164
- type = 2;
165
- break;
166
- case 'runtime':
167
- type = 4;
168
- break;
169
- case 'test':
170
- type = 5;
171
- break;
172
- }
173
- if (type !== -1) {
174
- const current = supplement.find(seg => seg[0] === groupId && seg[1] === artifactId);
175
- if (current) {
176
- const t = parseInt(current[3]);
177
- if (t !== type) {
178
- const rangeVer = isSemVer(version);
179
- if (!isSemVer(current[2])) {
180
- if (rangeVer || type < t) {
159
+ if (target) {
160
+ if (target.dependencies) {
161
+ let found = false;
162
+ for (const { groupId, artifactId, version, scope } of target.dependencies) {
163
+ if (scope && (dependencyScopes === true || dependencyScopes === 1 || hasScope(scope))) {
164
+ let type = -1;
165
+ switch (scope) {
166
+ case 'compile':
167
+ type = 0;
168
+ break;
169
+ case 'provided':
170
+ type = 2;
171
+ break;
172
+ case 'runtime':
173
+ type = 4;
174
+ break;
175
+ case 'test':
176
+ type = 5;
177
+ break;
178
+ }
179
+ if (type !== -1) {
180
+ const current = supplement.find(seg => seg[0] === groupId && seg[1] === artifactId);
181
+ if (current) {
182
+ const t = parseInt(current[3]);
183
+ if (t !== type) {
184
+ const rangeVer = isSemVer(version);
185
+ if (!isSemVer(current[2])) {
186
+ if (rangeVer || type < t) {
187
+ current[2] = version;
188
+ found = true;
189
+ }
190
+ }
191
+ else if (rangeVer && type < t) {
181
192
  current[2] = version;
182
193
  found = true;
183
194
  }
195
+ current[3] = '0';
184
196
  }
185
- else if (rangeVer && type < t) {
197
+ else if (isUpgrade(current[2], version)) {
186
198
  current[2] = version;
187
199
  found = true;
188
200
  }
189
- current[3] = '0';
190
201
  }
191
- else if (isUpgrade(current[2], version)) {
192
- current[2] = version;
202
+ else {
203
+ supplement.push([groupId, artifactId, version, type.toString()]);
193
204
  found = true;
194
205
  }
195
206
  }
196
- else {
197
- supplement.push([groupId, artifactId, version, type.toString()]);
198
- found = true;
199
- }
200
207
  }
201
208
  }
209
+ if (found && (snapshot || isUpgrade(item[2], target.version))) {
210
+ item[2] = target.version;
211
+ }
202
212
  }
203
- if (found && (snapshot || isUpgrade(item[2], target.version))) {
204
- item[2] = target.version;
205
- }
213
+ break;
206
214
  }
207
- break;
208
215
  }
209
216
  for (const item of supplement) {
210
217
  const [groupId, artifactId] = item;
@@ -231,23 +238,20 @@ function finalize(instance) {
231
238
  }
232
239
  return a[1] < b[1] ? -1 : 1;
233
240
  });
234
- if (!kotlin && items.some(seg => seg[1].endsWith('-ktx'))) {
235
- setModified(Document.updateGradle(source, ['plugins'], "id 'kotlin-android'", { multiple: true }));
236
- }
237
241
  const match = REGEXP_DEPENDENCIES.exec(source);
238
242
  if (match) {
239
- const newLine = (0, util_1.getNewline)(source);
243
+ const newLine = getNewline(source);
240
244
  const gradleDir = path.join(this.baseDirectory, 'gradle');
241
245
  const template = instance.findTemplate(gradleDir, "libs.versions.toml", { detect: true, subDir: language, throwsDoesNotExist: false });
242
246
  let content = match[1], named = false, versioning = false, indent;
243
- if (template.localUri && template.source) {
247
+ if (template.source && template.localUri && instance.canWrite(template.localUri, { ownPermissionOnly: true })) {
244
248
  versioning = kotlin && versionCatalog !== false || !!versionCatalog;
245
249
  if (versioning || template.existing) {
246
250
  const libs = {};
247
251
  const versions = {};
248
252
  let config = template.source, catalog;
249
- while (catalog = REGEXP_VERSIONS.exec(config)) {
250
- versions[catalog[1]] = (catalog[2] || catalog[3] || catalog[4]).trim();
253
+ for (const ref of config.matchAll(REGEXP_VERSIONS)) {
254
+ versions[ref[1]] = (ref[2] || ref[3] || ref[4]).trim();
251
255
  }
252
256
  while (catalog = REGEXP_VERSIONS_LIB.exec(config)) {
253
257
  const lib = {};
@@ -280,15 +284,15 @@ function finalize(instance) {
280
284
  const version = ref ? versions[ref] : lib.version;
281
285
  if (version && checkVersion(item, version)) {
282
286
  if (ref) {
283
- const target = new RegExp(`\\s${(0, types_1.escapePattern)(ref)}\\s*=\\s*(?:"([^":]+)"|'([^':]+)')`, 'd').exec(config);
284
- if (target) {
287
+ const target = new RegExp(`\\s${escapePattern(ref)}\\s*=\\s*(?:"([^"]+)"|'([^']+)')`, 'd').exec(config);
288
+ if (target?.indices) {
285
289
  const [start, end] = target.indices[1] || target.indices[2];
286
- config = (0, util_1.spliceString)(config, start, end, versions[ref] = item[2], REGEXP_VERSIONS_LIB);
290
+ config = spliceString(config, start, end, versions[ref] = item[2], REGEXP_VERSIONS_LIB);
287
291
  }
288
292
  }
289
293
  else if (lib.version_indices) {
290
294
  const [start, end] = lib.version_indices;
291
- config = (0, util_1.spliceString)(config, start, end, lib.version = item[2], REGEXP_VERSIONS_LIB);
295
+ config = spliceString(config, start, end, lib.version = item[2], REGEXP_VERSIONS_LIB);
292
296
  }
293
297
  }
294
298
  }
@@ -297,12 +301,11 @@ function finalize(instance) {
297
301
  }
298
302
  if (versioning && items.length > 0) {
299
303
  let output = '[libraries]' + newLine, outputVer = '';
300
- for (let i = 0, length = items.length; i < length; ++i) {
301
- const item = items[i];
304
+ for (const item of items) {
302
305
  const [group, name, version] = item;
303
- let key = group.replaceAll('.', '-');
306
+ let key = group.replace(/\./g, '-');
304
307
  if (libs[key]) {
305
- key += '-' + name.replaceAll('.', '-');
308
+ key += '-' + name.replace(/\./g, '-');
306
309
  }
307
310
  let versionRef;
308
311
  found: {
@@ -316,8 +319,6 @@ function finalize(instance) {
316
319
  }
317
320
  }
318
321
  }
319
- }
320
- if (!versionRef) {
321
322
  if (versions[versionRef = toCamelCase(name)]) {
322
323
  const prefix = group.split('.').filter(seg => seg !== name).pop();
323
324
  if (prefix) {
@@ -325,9 +326,9 @@ function finalize(instance) {
325
326
  }
326
327
  else {
327
328
  const baseRef = versionRef;
328
- let j = 1;
329
+ let i = 1;
329
330
  do {
330
- versionRef = baseRef + j++;
331
+ versionRef = baseRef + i++;
331
332
  } while (versions[versionRef]);
332
333
  }
333
334
  }
@@ -335,7 +336,7 @@ function finalize(instance) {
335
336
  outputVer += versionRef + ` = "${version}"` + newLine;
336
337
  }
337
338
  output += key + ` = { group = "${group}", name = "${name}", version.ref = "${versionRef}" }` + newLine;
338
- item[0] = 'libs.' + key.replaceAll('-', '.');
339
+ item[0] = 'libs.' + key.replace(/-/g, '.');
339
340
  item[1] = '';
340
341
  item[2] = '';
341
342
  libs[key] = { group, name, "version.ref": versionRef };
@@ -354,7 +355,7 @@ function finalize(instance) {
354
355
  }
355
356
  REGEXP_VERSIONS.lastIndex = 0;
356
357
  }
357
- if (instance.canWrite(template.localUri, { ownPermissionOnly: true }) && Document.createDir(gradleDir)) {
358
+ if (Document.createDir(gradleDir)) {
358
359
  try {
359
360
  fs.writeFileSync(template.localUri, config, 'utf8');
360
361
  this.add(template.localUri);
@@ -373,16 +374,14 @@ function finalize(instance) {
373
374
  let method;
374
375
  while (method = pattern.exec(content)) {
375
376
  let group, name, version;
376
- if ((0, types_1.isString)(method[1])) {
377
+ if (isString(method[1])) {
377
378
  indent ||= method[1];
378
379
  }
379
380
  if (method[3]) {
380
381
  [group, name, version] = method[3].trim().split(/\s*:\s*/);
381
382
  }
382
383
  else if (method[4]) {
383
- const params = /(group|name|version)\s*[=:]\s*(?:"([^"]+)"|'([^']+)')/g;
384
- let param;
385
- while (param = params.exec(method[4])) {
384
+ for (const param of method[4].matchAll(/(group|name|version)\s*[=:]\s*(?:"([^"]+)"|'([^']+)')/g)) {
386
385
  const value = (param[2] || param[3]).trim();
387
386
  switch (param[1]) {
388
387
  case 'group':
@@ -410,57 +409,41 @@ function finalize(instance) {
410
409
  version = '';
411
410
  }
412
411
  if (checkVersion(item, version, method[0])) {
413
- content = (0, util_1.spliceString)(content, method.index, method.index + method[0].length, method[1] + writeMethod(kotlin, named, item, method[4], method[2]) + newLine, pattern);
412
+ content = spliceString(content, method.index, method.index + method[0].length, method[1] + writeMethod(kotlin, named, item, method[4], method[2]) + newLine, pattern);
414
413
  modified = true;
415
414
  }
416
415
  }
417
416
  }
418
417
  }
419
418
  }
420
- indent ||= (0, util_1.getIndent)(match[1]);
419
+ indent ||= getIndent(match[1]);
421
420
  content = items.reduce((a, b) => a + indent + writeMethod(kotlin, named, b) + newLine, content);
422
421
  modified = true;
423
422
  }
424
423
  setDependencies(match, content);
425
424
  }
426
- if (items.some(seg => seg[0] === 'androidx.compose.ui')) {
427
- let output = source;
428
- if (kotlin) {
429
- output = Document.updateGradle(output, ['plugins'], 'kotlin("android")');
425
+ if (!kotlin && items.some(seg => seg[0] === 'androidx.compose.ui')) {
426
+ const stdLib = instance.findVersion('org.jetbrains.kotlin:kotlin-stdlib');
427
+ if (stdLib.startsWith('1.')) {
428
+ let output = source;
430
429
  output = Document.updateGradle(output, ['android', 'buildFeatures'], 'compose = true');
430
+ output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion = '${instance.findVersion('kotlinCompilerExtensionVersion', '1.5.15')}'`, updateOpts());
431
+ setModified(output);
431
432
  }
432
- else {
433
- const stdLib = instance.findVersion('org.jetbrains.kotlin:kotlin-stdlib', "2.2.21");
434
- output = Document.updateGradle(output, ['plugins'], "id 'org.jetbrains.kotlin.android'", { upgrade: true, multiple: true, addendum: `version '${stdLib}'` });
435
- output = Document.updateGradle(output, ['android', 'buildFeatures'], "compose true");
436
- if (stdLib.startsWith('1.')) {
437
- output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion '${instance.findVersion('kotlinCompilerExtensionVersion', "1.5.15")}'`, true);
438
- }
439
- if (upgrade) {
440
- output = Document.updateGradle(output, ['android', 'kotlinOptions'], `jvmTarget = '${javaVersion}'`, true);
441
- }
442
- else {
443
- output = Document.updateGradle(output, ['android', 'kotlinOptions'], "jvmTarget = '1.8'");
444
- jvmTarget = '1_8';
445
- }
446
- }
447
- setModified(output);
448
433
  }
449
434
  }
450
435
  if (libraries) {
451
436
  const match = REGEXP_DEPENDENCIES.exec(source);
452
437
  if (match) {
453
- let content = match[1], method, indent;
454
- const pattern = kotlin ? REGEXP_LIBRARY_KOTLIN : REGEXP_LIBRARY;
455
- pattern.lastIndex = 0;
456
- while (method = pattern.exec(content)) {
438
+ let content = match[1], indent;
439
+ for (const method of content.matchAll(kotlin ? REGEXP_LIBRARY_KOTLIN : REGEXP_LIBRARY)) {
457
440
  const attr = (method[2] || method[4]);
458
- if ((0, types_1.isArray)(libraries[attr])) {
441
+ if (isArray(libraries[attr])) {
459
442
  let index = -1;
460
443
  switch (attr) {
461
444
  case 'project':
462
445
  case 'files': {
463
- const pathname = (0, util_1.trimQuote)(method[3]);
446
+ const pathname = trimQuote(method[3]);
464
447
  index = libraries[attr].findIndex(value => value === pathname);
465
448
  break;
466
449
  }
@@ -470,7 +453,7 @@ function finalize(instance) {
470
453
  if (dir && include) {
471
454
  const compare = (from, orig) => {
472
455
  try {
473
- return (0, types_1.isArray)(from) && from.sort().toString() === JSON.parse(`[${orig}]`).sort().toString();
456
+ return isArray(from) && from.sort().toString() === JSON.parse(`[${orig}]`).sort().toString();
474
457
  }
475
458
  catch {
476
459
  return false;
@@ -490,29 +473,29 @@ function finalize(instance) {
490
473
  if (index !== -1) {
491
474
  libraries[attr].splice(index, 1);
492
475
  }
493
- if ((0, types_1.isString)(method[1])) {
476
+ if (isString(method[1])) {
494
477
  indent ||= method[1];
495
478
  }
496
479
  }
497
480
  }
498
481
  const { project, files, fileTree } = libraries;
499
- if ((0, types_1.isArray)(project) || (0, types_1.isArray)(files) || (0, types_1.isArray)(fileTree)) {
500
- indent ||= (0, util_1.getIndent)(match[1]);
501
- const newLine = (0, util_1.getNewline)(source);
502
- const writeImpl = (name, value) => indent + 'implementation' + (kotlin ? `(${name}(${(0, util_1.wrapQuote)(value)}))` : ` ${name}(${(0, util_1.wrapQuote)(value)})`) + newLine;
503
- if ((0, types_1.isArray)(project)) {
482
+ if (isArray(project) || isArray(files) || isArray(fileTree)) {
483
+ indent ||= getIndent(match[1]);
484
+ const newLine = getNewline(source);
485
+ const writeImpl = (name, value) => indent + 'implementation' + (kotlin ? `(${name}(${wrapQuote(value)}))` : ` ${name}(${wrapQuote(value)})`) + newLine;
486
+ if (isArray(project)) {
504
487
  content = project.reduce((a, b) => a + writeImpl('project', b), content);
505
488
  modified = true;
506
489
  }
507
- if ((0, types_1.isArray)(files)) {
490
+ if (isArray(files)) {
508
491
  content = files.reduce((a, b) => a + writeImpl('files', b), content);
509
492
  modified = true;
510
493
  }
511
- if ((0, types_1.isArray)(fileTree)) {
494
+ if (isArray(fileTree)) {
512
495
  for (const item of fileTree) {
513
- if ((0, types_1.isString)(item.dir) && (0, types_1.isArray)(item.include)) {
514
- const dir = (0, util_1.wrapQuote)(item.dir);
515
- const include = item.include.map(value => (0, util_1.wrapQuote)(value)).join(', ');
496
+ if (isString(item.dir) && isArray(item.include)) {
497
+ const dir = wrapQuote(item.dir);
498
+ const include = item.include.map(value => wrapQuote(value)).join(', ');
516
499
  content += indent + 'implementation';
517
500
  if (kotlin) {
518
501
  content += `(fileTree(mapOf("dir" to ${dir}, "include" to listOf(${include}))))`;
@@ -529,68 +512,65 @@ function finalize(instance) {
529
512
  }
530
513
  }
531
514
  }
532
- if (upgrade || jvmTarget) {
533
- const compatibility = 'JavaVersion.VERSION_' + (upgrade ? javaVersion.toString().replace(/\./g, '_') : jvmTarget);
515
+ if (upgrade) {
516
+ const compatibility = 'JavaVersion.VERSION_' + javaVersion.toString().replace(/\./g, '_');
517
+ const sourceCompat = valueFor('sourceCompatibility', compatibility, kotlin);
518
+ const targetCompat = valueFor('targetCompatibility', compatibility, kotlin);
534
519
  let output = source;
535
- if (kotlin) {
536
- output = Document.updateGradle(output, ['java'], 'sourceCompatibility = ' + compatibility, upgrade);
537
- output = Document.updateGradle(output, ['java'], 'targetCompatibility = ' + compatibility, upgrade);
538
- output = Document.updateGradle(output, ['android', 'kotlinOptions'], `jvmTarget = "${javaVersion}"`, upgrade);
520
+ output = Document.updateGradle(output, ['java'], sourceCompat, updateOpts(true));
521
+ if (output === source) {
522
+ output = Document.updateGradle(output, ['android', 'compileOptions'], sourceCompat, updateOpts());
523
+ output = Document.updateGradle(output, ['android', 'compileOptions'], targetCompat, updateOpts());
539
524
  }
540
525
  else {
541
- output = Document.updateGradle(output, ['android', 'compileOptions'], 'sourceCompatibility ' + compatibility, upgrade);
542
- output = Document.updateGradle(output, ['android', 'compileOptions'], 'targetCompatibility ' + compatibility, upgrade);
526
+ output = Document.updateGradle(output, ['java'], targetCompat, updateOpts(true));
543
527
  }
544
528
  setModified(output);
545
529
  }
546
530
  if (jvmToolchain) {
547
531
  let output = source;
548
532
  if (language === 'java') {
549
- output = Document.updateGradle(output, ['java', 'toolchain'], kotlin ? `languageVersion.set(JavaLanguageVersion.of(${jvmToolchain}))` : `languageVersion = JavaLanguageVersion.of(${jvmToolchain})`, true);
533
+ output = Document.updateGradle(output, ['java', 'toolchain'], kotlin ? `languageVersion.set(JavaLanguageVersion.of(${jvmToolchain}))` : `languageVersion = JavaLanguageVersion.of(${jvmToolchain})`, updateOpts());
550
534
  }
551
535
  else {
552
- output = Document.updateGradle(output, ['kotlin'], kotlin ? `jvmToolchain(${jvmToolchain})` : 'jvmToolchain ' + jvmToolchain, true);
536
+ output = Document.updateGradle(output, ['kotlin'], kotlin ? `jvmToolchain(${jvmToolchain})` : 'jvmToolchain ' + jvmToolchain, updateOpts());
553
537
  }
554
538
  setModified(output);
555
539
  }
556
- if (!existing) {
557
- const targetAPI = instance.targetAPI;
540
+ if (targetAPI) {
558
541
  let output = source;
559
- if (targetAPI) {
560
- const [compileSdk, targetSdk, updateOnly] = typeof targetAPI === 'string' ? [`"android-${targetAPI}"`, `"${targetAPI}"`, true] : [targetAPI, targetAPI, targetAPI >= 33];
561
- let content = Document.updateGradle(output, ['android'], kotlin ? `compileSdkVersion(${compileSdk})` : 'compileSdkVersion ' + compileSdk, { upgrade: true, updateOnly });
562
- if (content === output) {
563
- output = Document.updateGradle(output, ['android'], kotlin ? `compileSdk(${compileSdk})` : 'compileSdk ' + compileSdk, true);
564
- }
565
- else {
566
- output = content;
567
- }
568
- content = Document.updateGradle(output, ['android', 'defaultConfig'], kotlin ? `targetSdkVersion(${targetSdk})` : 'targetSdkVersion ' + targetSdk, { upgrade: true, updateOnly });
569
- if (content === output) {
570
- output = Document.updateGradle(output, ['android', 'defaultConfig'], kotlin ? `targetSdk(${targetSdk})` : 'targetSdk ' + targetSdk, true);
571
- }
572
- else {
573
- output = content;
574
- }
575
- const version = instance.findVersion('buildToolsVersion');
576
- if (version) {
577
- output = Document.updateGradle(output, ['android'], kotlin ? `buildToolsVersion = "${version}"` : `buildToolsVersion "${version}"`, true);
542
+ const tryInline = (compileSdk) => {
543
+ output = Document.updateGradle(output, ['android'], valueFor('compileSdk', compileSdk, kotlin), updateOpts(true));
544
+ return output !== source;
545
+ };
546
+ if (typeof targetAPI === 'number') {
547
+ const targetMajor = Math.floor(targetAPI);
548
+ output = Document.updateGradle(output, ['android', /version\s*=?\s*(release\(\d+\))/], [`release(${targetMajor})`, valueFor('minorApiLevel', Math.trunc((targetAPI - targetMajor) * 10), true)], updateOpts(true));
549
+ if (output === source) {
550
+ tryInline(targetMajor);
578
551
  }
579
552
  }
580
- if (applicationId) {
581
- output = Document.updateGradle(output, ['android', 'defaultConfig'], (kotlin ? 'applicationId = ' : 'applicationId ') + `"${applicationId}"`, true);
553
+ else if (tryInline(`"android-${targetAPI}"`)) {
554
+ output = Document.updateGradle(output, ['android', 'defaultConfig'], valueFor('targetSdk', targetAPI, kotlin, true), updateOpts());
555
+ }
556
+ const version = instance.findVersion('buildToolsVersion');
557
+ if (version) {
558
+ output = Document.updateGradle(output, ['android'], valueFor('buildToolsVersion', version, kotlin, true), updateOpts());
582
559
  }
583
560
  setModified(output);
584
561
  }
562
+ if (applicationId) {
563
+ setModified(Document.updateGradle(source, ['android', 'defaultConfig'], valueFor('applicationId', applicationId, kotlin, true), updateOpts()));
564
+ }
585
565
  if (dataBinding) {
586
- setModified(Document.updateGradle(source, ['android', 'buildFeatures'], kotlin ? 'dataBinding = true' : 'dataBinding true', true));
566
+ setModified(Document.updateGradle(source, ['android', 'buildFeatures'], valueFor('dataBinding', 'true', true), updateOpts()));
587
567
  }
588
568
  if (namespace) {
589
- setModified(Document.updateGradle(source, ['android'], (kotlin ? 'namespace = ' : 'namespace ') + `"${namespace}"`, true));
569
+ setModified(Document.updateGradle(source, ['android'], valueFor('namespace', namespace, true, true), updateOpts()));
590
570
  }
591
571
  if (profileable) {
592
572
  let name, items;
593
- if ((0, types_1.isArray)(profileable)) {
573
+ if (isArray(profileable)) {
594
574
  name = profileable[0];
595
575
  if (typeof name === 'string' && !name.startsWith('--')) {
596
576
  items = profileable.slice(1);
@@ -609,17 +589,17 @@ function finalize(instance) {
609
589
  }
610
590
  }
611
591
  name ||= 'debug';
612
- setModified(Document.updateGradle(source, ['android', 'buildTypes', kotlin ? 'getByName("release")' : 'release'], 'signingConfig ' + (kotlin ? `= signingConfigs.getByName("${name}")` : 'signingConfigs.' + name), true));
613
- if ((0, types_1.isArray)(items)) {
592
+ setModified(Document.updateGradle(source, ['android', 'buildTypes', kotlin ? 'getByName("release")' : 'release'], 'signingConfig ' + (kotlin ? `= signingConfigs.getByName("${name}")` : 'signingConfigs.' + name), updateOpts()));
593
+ if (isArray(items)) {
614
594
  const parameters = items.map(value => `"${value}"`).join(', ');
615
- setModified(Document.updateGradle(source, ['android', 'aaptOptions'], 'additionalParameters ' + (kotlin ? `= [${parameters}]` : parameters), true));
595
+ setModified(Document.updateGradle(source, ['android', 'aaptOptions'], 'additionalParameters ' + (kotlin ? `= [${parameters}]` : parameters), updateOpts()));
616
596
  }
617
597
  }
618
598
  if (versionName) {
619
- setModified(Document.updateGradle(source, ['android', 'defaultConfig'], (kotlin ? 'versionName = ' : 'versionName ') + `"${versionName}"`, true));
599
+ setModified(Document.updateGradle(source, ['android', 'defaultConfig'], valueFor('versionName', versionName, kotlin, true), updateOpts()));
620
600
  }
621
601
  if (versionCode) {
622
- setModified(Document.updateGradle(source, ['android', 'defaultConfig'], (kotlin ? 'versionCode = ' : 'versionCode ') + versionCode, true));
602
+ setModified(Document.updateGradle(source, ['android', 'defaultConfig'], valueFor('versionCode', versionCode, kotlin), updateOpts()));
623
603
  }
624
604
  if (modified || !existing) {
625
605
  try {
@@ -678,4 +658,5 @@ function finalize(instance) {
678
658
  }
679
659
  }
680
660
  }
661
+
681
662
  module.exports = finalize;