@pi-r/android 0.11.3 → 0.12.1

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,20 @@
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
- const REGEXP_DEPENDENCY = /([ \t]*)([A-Za-z_$][\w$]*)(?:\s*\(?\s*(?:module\(?\s*)?["']([^"']+)["']\s*\)?|\s+((?:\s*(?:group|name|version)\s*:\s*(?:"(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+')\s*,?){3}))?/gd;
10
- const REGEXP_DEPENDENCY_KOTLIN = /([ \t]*)([A-Za-z_$][\w$]*)\((?:\s*(?:(?:module\(\s*)?"([^"]+)"|((?:\s*(?:group|name|version)\s*=\s*"(?:[^"]|(?<=\\)")+"\s*,?){3}))\s*\))?/gd;
11
- 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
- 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;
10
+ const REGEXP_DEPENDENCY = /([ \t]*)([A-Za-z_$][\w$]*)(?:\s*\(?\s*(?:module\(?\s*)?["']([^"']+)["']\s*\)?|\s+((?:\s*(?:group|name|version)\s*:\s*(?:"(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+')\s*,?){3}))?/g;
11
+ const REGEXP_DEPENDENCY_KOTLIN = /([ \t]*)([A-Za-z_$][\w$]*)\((?:\s*(?:(?:module\(\s*)?"([^"]+)"|((?:\s*(?:group|name|version)\s*=\s*"(?:[^"]|(?<=\\)")+"\s*,?){3}))\s*\))?/g;
12
+ const REGEXP_LIBRARY = /([ \t]*)implementation\s+(?:(project|files)\(\s*("(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+')\s*\)|(fileTree)\(\s*((?:\s*(?:dir|include)\s*:\s*(?:"(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+'|\[[^\]]+\])\s*,?){2})\s*\))[ \t\r]*\n/g;
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/g;
14
+ const REGEXP_PLATFORM = /([ \t]*)implementation\s+platform\(\s*("(?:[^"]|(?<=\\)")+"|'(?:[^']|(?<=\\)')+')\s*\)[ \t\r]*\n/g;
15
+ const REGEXP_PLATFORM_KOTLIN = /([ \t]*)implementation\(\s*platform\(\s*"(.+)"\s*\)\s*\)[ \t\r]*\n/g;
16
+ const REGEXP_VERSIONS = /(\S+)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{(?:\s*(?:require|strictly|prefer|reject(?:All)?)\s*=\s*(?:"[^"]+"|'[^']+')\s*,?)+\s*\}))/g;
17
+ 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
18
  function isUpgrade(version, pending) {
16
19
  if (isSemVer(pending)) {
17
20
  return true;
@@ -29,7 +32,7 @@ function isUpgrade(version, pending) {
29
32
  return true;
30
33
  }
31
34
  if (isNaN(b) || b < a) {
32
- break;
35
+ return false;
33
36
  }
34
37
  }
35
38
  }
@@ -90,15 +93,21 @@ function writeMethod(kotlin, named, item, args = '', prefix = 'implementation')
90
93
  else {
91
94
  dependency = item.slice(0, 3).join(':');
92
95
  if (dependency.endsWith(':')) {
93
- dependency = dependency.substring(0, dependency.length - 1);
96
+ dependency = dependency.slice(0, -1);
94
97
  }
95
98
  dependency = kotlin ? `("${dependency}")` : ` '${dependency}'`;
96
99
  }
97
100
  return prefix + dependency;
98
101
  }
102
+ function valueFor(name, value, kotlin, quote = false) {
103
+ value = value.toString();
104
+ const q = quote ? kotlin && !value.includes('"') || value.includes("'") ? '"' : "'" : '';
105
+ return `${name} ${kotlin ? '= ' : ''}${q + value + q}`;
106
+ }
99
107
  const isLatest = (value) => value === '' || value.startsWith('latest.');
100
108
  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);
109
+ const updateOpts = (updateOnly = false) => ({ upgrade: true, updateOnly });
110
+ const writeOutput = (match, source, value) => spliceString(source, match.index, match.index + match[0].length, value);
102
111
  const toCamelCase = (value) => value.replace(/-([a-z])/gi, (...capture) => capture[1].toUpperCase());
103
112
  function finalize(instance) {
104
113
  const { profileable, dependencies, libraries, dataBinding, jvmToolchain, versionName, versionCode, namespace, applicationId, mainParentDir } = instance.config;
@@ -108,8 +117,9 @@ function finalize(instance) {
108
117
  let { localUri, source, existing, kotlin = false, language } = instance.findTemplate(path.join(this.baseDirectory, mainParentDir), "build.gradle", { detect: instance.detect(this), languageOf: 'gradle' });
109
118
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
110
119
  const javaVersion = instance.config.javaVersion;
111
- let jvmTarget, modified = false;
120
+ const targetAPI = instance.targetAPI;
112
121
  const upgrade = javaVersion > 0;
122
+ let modified = false;
113
123
  const setModified = (output) => {
114
124
  if (output !== source) {
115
125
  source = output;
@@ -118,13 +128,13 @@ function finalize(instance) {
118
128
  };
119
129
  const setDependencies = (match, output) => {
120
130
  if (modified || !existing) {
121
- setModified((0, util_1.spliceString)(source, match.index, match.index + match[0].length, `dependencies {${output}}`));
131
+ setModified(spliceString(source, match.index, match.index + match[0].length, `dependencies {${output}}`));
122
132
  }
123
133
  };
124
134
  if (dependencies) {
125
135
  const { dependencyScopes, versionCatalog } = instance.config;
126
- let mavenData;
127
- const hasScope = (value) => (0, types_1.isArray)(dependencyScopes) && dependencyScopes.includes(value) || dependencyScopes === value;
136
+ let mavenData = null;
137
+ const hasScope = (value) => isArray(dependencyScopes) && dependencyScopes.includes(value) || dependencyScopes === value;
128
138
  const snapshot = dependencyScopes === 1 || hasScope('snapshot');
129
139
  const constraints = hasScope('constraints');
130
140
  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]);
@@ -146,69 +156,66 @@ function finalize(instance) {
146
156
  if (dependencyScopes && (mavenData = getData())) {
147
157
  const supplement = [];
148
158
  for (const item of items) {
149
- const [gId, id] = item;
150
- 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
+ const target = mavenData[item[0]]?.find(group => group.artifactId === item[1]);
160
+ if (target) {
161
+ if (target.dependencies) {
162
+ let found = false;
163
+ for (const { groupId, artifactId, version, scope } of target.dependencies) {
164
+ if (scope && (dependencyScopes === true || dependencyScopes === 1 || hasScope(scope))) {
165
+ let type = -1;
166
+ switch (scope) {
167
+ case 'compile':
168
+ type = 0;
169
+ break;
170
+ case 'provided':
171
+ type = 2;
172
+ break;
173
+ case 'runtime':
174
+ type = 4;
175
+ break;
176
+ case 'test':
177
+ type = 5;
178
+ break;
179
+ }
180
+ if (type !== -1) {
181
+ const current = supplement.find(seg => seg[0] === groupId && seg[1] === artifactId);
182
+ if (current) {
183
+ const t = parseInt(current[3]);
184
+ if (t !== type) {
185
+ const rangeVer = isSemVer(version);
186
+ if (!isSemVer(current[2])) {
187
+ if (rangeVer || type < t) {
188
+ current[2] = version;
189
+ found = true;
190
+ }
191
+ }
192
+ else if (rangeVer && type < t) {
181
193
  current[2] = version;
182
194
  found = true;
183
195
  }
196
+ current[3] = '0';
184
197
  }
185
- else if (rangeVer && type < t) {
198
+ else if (isUpgrade(current[2], version)) {
186
199
  current[2] = version;
187
200
  found = true;
188
201
  }
189
- current[3] = '0';
190
202
  }
191
- else if (isUpgrade(current[2], version)) {
192
- current[2] = version;
203
+ else {
204
+ supplement.push([groupId, artifactId, version, type.toString()]);
193
205
  found = true;
194
206
  }
195
207
  }
196
- else {
197
- supplement.push([groupId, artifactId, version, type.toString()]);
198
- found = true;
199
- }
200
208
  }
201
209
  }
210
+ if (found && (snapshot || isUpgrade(item[2], target.version))) {
211
+ item[2] = target.version;
212
+ }
202
213
  }
203
- if (found && (snapshot || isUpgrade(item[2], target.version))) {
204
- item[2] = target.version;
205
- }
214
+ break;
206
215
  }
207
- break;
208
216
  }
209
217
  for (const item of supplement) {
210
- const [groupId, artifactId] = item;
211
- const index = items.findIndex(seg => seg[0] === groupId && seg[1] === artifactId);
218
+ const index = items.findIndex(seg => seg[0] === item[0] && seg[1] === item[1]);
212
219
  if (index === -1) {
213
220
  items.push(item);
214
221
  }
@@ -231,23 +238,33 @@ 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 });
246
+ const removeGroup = (id) => {
247
+ for (let i = 0; i < items.length; ++i) {
248
+ if (items[i][0] === id) {
249
+ items.splice(i--, 1);
250
+ }
251
+ }
252
+ };
242
253
  let content = match[1], named = false, versioning = false, indent;
243
- if (template.localUri && template.source) {
254
+ for (const platform of content.matchAll(kotlin ? REGEXP_PLATFORM_KOTLIN : REGEXP_PLATFORM)) {
255
+ const [group, name] = trimQuote(platform[1]).trim().split(':');
256
+ if (name.endsWith('-bom')) {
257
+ removeGroup(group);
258
+ }
259
+ }
260
+ if (template.source && template.localUri && instance.canWrite(template.localUri, { ownPermissionOnly: true })) {
244
261
  versioning = kotlin && versionCatalog !== false || !!versionCatalog;
245
262
  if (versioning || template.existing) {
246
263
  const libs = {};
247
264
  const versions = {};
248
265
  let config = template.source, catalog;
249
- while (catalog = REGEXP_VERSIONS.exec(config)) {
250
- versions[catalog[1]] = (catalog[2] || catalog[3] || catalog[4]).trim();
266
+ for (const ref of config.matchAll(REGEXP_VERSIONS)) {
267
+ versions[ref[1]] = (ref[2] || ref[3] || ref[4]).trim();
251
268
  }
252
269
  while (catalog = REGEXP_VERSIONS_LIB.exec(config)) {
253
270
  const lib = {};
@@ -272,6 +289,10 @@ function finalize(instance) {
272
289
  [group, name] = lib.module.split(':');
273
290
  }
274
291
  if (group && name) {
292
+ if (name.endsWith('-bom')) {
293
+ removeGroup(group);
294
+ continue;
295
+ }
275
296
  const index = items.findIndex(seg => seg[0] === group && seg[1] === name);
276
297
  if (index !== -1) {
277
298
  const item = items[index];
@@ -280,15 +301,15 @@ function finalize(instance) {
280
301
  const version = ref ? versions[ref] : lib.version;
281
302
  if (version && checkVersion(item, version)) {
282
303
  if (ref) {
283
- const target = new RegExp(`\\s${(0, types_1.escapePattern)(ref)}\\s*=\\s*(?:"([^":]+)"|'([^':]+)')`, 'd').exec(config);
284
- if (target) {
304
+ const target = new RegExp(`\\s${escapePattern(ref)}\\s*=\\s*(?:"([^"]+)"|'([^']+)')`, 'd').exec(config);
305
+ if (target?.indices) {
285
306
  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);
307
+ config = spliceString(config, start, end, versions[ref] = item[2], REGEXP_VERSIONS_LIB);
287
308
  }
288
309
  }
289
310
  else if (lib.version_indices) {
290
311
  const [start, end] = lib.version_indices;
291
- config = (0, util_1.spliceString)(config, start, end, lib.version = item[2], REGEXP_VERSIONS_LIB);
312
+ config = spliceString(config, start, end, lib.version = item[2], REGEXP_VERSIONS_LIB);
292
313
  }
293
314
  }
294
315
  }
@@ -297,12 +318,11 @@ function finalize(instance) {
297
318
  }
298
319
  if (versioning && items.length > 0) {
299
320
  let output = '[libraries]' + newLine, outputVer = '';
300
- for (let i = 0, length = items.length; i < length; ++i) {
301
- const item = items[i];
321
+ for (const item of items) {
302
322
  const [group, name, version] = item;
303
- let key = group.replaceAll('.', '-');
323
+ let key = group.replace(/\./g, '-');
304
324
  if (libs[key]) {
305
- key += '-' + name.replaceAll('.', '-');
325
+ key += '-' + name.replace(/\./g, '-');
306
326
  }
307
327
  let versionRef;
308
328
  found: {
@@ -316,8 +336,6 @@ function finalize(instance) {
316
336
  }
317
337
  }
318
338
  }
319
- }
320
- if (!versionRef) {
321
339
  if (versions[versionRef = toCamelCase(name)]) {
322
340
  const prefix = group.split('.').filter(seg => seg !== name).pop();
323
341
  if (prefix) {
@@ -325,9 +343,9 @@ function finalize(instance) {
325
343
  }
326
344
  else {
327
345
  const baseRef = versionRef;
328
- let j = 1;
346
+ let i = 1;
329
347
  do {
330
- versionRef = baseRef + j++;
348
+ versionRef = baseRef + i++;
331
349
  } while (versions[versionRef]);
332
350
  }
333
351
  }
@@ -335,7 +353,7 @@ function finalize(instance) {
335
353
  outputVer += versionRef + ` = "${version}"` + newLine;
336
354
  }
337
355
  output += key + ` = { group = "${group}", name = "${name}", version.ref = "${versionRef}" }` + newLine;
338
- item[0] = 'libs.' + key.replaceAll('-', '.');
356
+ item[0] = 'libs.' + key.replace(/-/g, '.');
339
357
  item[1] = '';
340
358
  item[2] = '';
341
359
  libs[key] = { group, name, "version.ref": versionRef };
@@ -354,7 +372,7 @@ function finalize(instance) {
354
372
  }
355
373
  REGEXP_VERSIONS.lastIndex = 0;
356
374
  }
357
- if (instance.canWrite(template.localUri, { ownPermissionOnly: true }) && Document.createDir(gradleDir)) {
375
+ if (Document.createDir(gradleDir)) {
358
376
  try {
359
377
  fs.writeFileSync(template.localUri, config, 'utf8');
360
378
  this.add(template.localUri);
@@ -373,16 +391,14 @@ function finalize(instance) {
373
391
  let method;
374
392
  while (method = pattern.exec(content)) {
375
393
  let group, name, version;
376
- if ((0, types_1.isString)(method[1])) {
394
+ if (isString(method[1])) {
377
395
  indent ||= method[1];
378
396
  }
379
397
  if (method[3]) {
380
398
  [group, name, version] = method[3].trim().split(/\s*:\s*/);
381
399
  }
382
400
  else if (method[4]) {
383
- const params = /(group|name|version)\s*[=:]\s*(?:"([^"]+)"|'([^']+)')/g;
384
- let param;
385
- while (param = params.exec(method[4])) {
401
+ for (const param of method[4].matchAll(/(group|name|version)\s*[=:]\s*(?:"([^"]+)"|'([^']+)')/g)) {
386
402
  const value = (param[2] || param[3]).trim();
387
403
  switch (param[1]) {
388
404
  case 'group':
@@ -410,67 +426,51 @@ function finalize(instance) {
410
426
  version = '';
411
427
  }
412
428
  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);
429
+ content = spliceString(content, method.index, method.index + method[0].length, method[1] + writeMethod(kotlin, named, item, method[4], method[2]) + newLine, pattern);
414
430
  modified = true;
415
431
  }
416
432
  }
417
433
  }
418
434
  }
419
435
  }
420
- indent ||= (0, util_1.getIndent)(match[1]);
436
+ indent ||= getIndent(match[1]);
421
437
  content = items.reduce((a, b) => a + indent + writeMethod(kotlin, named, b) + newLine, content);
422
438
  modified = true;
423
439
  }
424
440
  setDependencies(match, content);
425
441
  }
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")');
442
+ if (!kotlin && items.some(seg => seg[0] === 'androidx.compose.ui')) {
443
+ const stdLib = instance.findVersion('org.jetbrains.kotlin:kotlin-stdlib');
444
+ if (stdLib.startsWith('1.')) {
445
+ let output = source;
430
446
  output = Document.updateGradle(output, ['android', 'buildFeatures'], 'compose = true');
447
+ output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion = '${instance.findVersion('kotlinCompilerExtensionVersion', '1.5.15')}'`, updateOpts());
448
+ setModified(output);
431
449
  }
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
450
  }
449
451
  }
450
452
  if (libraries) {
451
453
  const match = REGEXP_DEPENDENCIES.exec(source);
452
454
  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)) {
455
+ let content = match[1], indent;
456
+ for (const method of content.matchAll(kotlin ? REGEXP_LIBRARY_KOTLIN : REGEXP_LIBRARY)) {
457
457
  const attr = (method[2] || method[4]);
458
- if ((0, types_1.isArray)(libraries[attr])) {
458
+ if (isArray(libraries[attr])) {
459
459
  let index = -1;
460
460
  switch (attr) {
461
461
  case 'project':
462
462
  case 'files': {
463
- const pathname = (0, util_1.trimQuote)(method[3]);
463
+ const pathname = trimQuote(method[3]);
464
464
  index = libraries[attr].findIndex(value => value === pathname);
465
465
  break;
466
466
  }
467
467
  case 'fileTree': {
468
- const dir = /"dir"\s+to\s+"(.+?)"(?:\s*,|$)/.exec(match[5])?.[1];
469
- const include = /"include"\s+to\s+listOf\((.+?)\)(?:\s*,|$)/.exec(match[5])?.[1];
468
+ const dir = (kotlin ? /"dir"\s+to\s+"(.+)"(?:\s*,|$)/ : /\bdir\s*:\s*["'](.+)["'](?:\s*,|$)/).exec(match[5])?.[1];
469
+ const include = (kotlin ? /"include"\s+to\s+listOf\(([^)]+)\)(?:\s*,|$)/ : /\binclude\s*:\s*\[(.+)\](?:\s*,|$)/).exec(match[5])?.[1];
470
470
  if (dir && include) {
471
471
  const compare = (from, orig) => {
472
472
  try {
473
- return (0, types_1.isArray)(from) && from.sort().toString() === JSON.parse(`[${orig}]`).sort().toString();
473
+ return isArray(from) && from.sort().toString() === JSON.parse(`[${orig}]`).sort().toString();
474
474
  }
475
475
  catch {
476
476
  return false;
@@ -490,29 +490,29 @@ function finalize(instance) {
490
490
  if (index !== -1) {
491
491
  libraries[attr].splice(index, 1);
492
492
  }
493
- if ((0, types_1.isString)(method[1])) {
493
+ if (isString(method[1])) {
494
494
  indent ||= method[1];
495
495
  }
496
496
  }
497
497
  }
498
498
  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)) {
499
+ if (isArray(project) || isArray(files) || isArray(fileTree)) {
500
+ indent ||= getIndent(match[1]);
501
+ const newLine = getNewline(source);
502
+ const writeImpl = (name, value) => indent + 'implementation' + (kotlin ? `(${name}(${wrapQuote(value)}))` : ` ${name}(${wrapQuote(value)})`) + newLine;
503
+ if (isArray(project)) {
504
504
  content = project.reduce((a, b) => a + writeImpl('project', b), content);
505
505
  modified = true;
506
506
  }
507
- if ((0, types_1.isArray)(files)) {
507
+ if (isArray(files)) {
508
508
  content = files.reduce((a, b) => a + writeImpl('files', b), content);
509
509
  modified = true;
510
510
  }
511
- if ((0, types_1.isArray)(fileTree)) {
511
+ if (isArray(fileTree)) {
512
512
  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(', ');
513
+ if (isString(item.dir) && isArray(item.include)) {
514
+ const dir = wrapQuote(item.dir);
515
+ const include = item.include.map(value => wrapQuote(value)).join(', ');
516
516
  content += indent + 'implementation';
517
517
  if (kotlin) {
518
518
  content += `(fileTree(mapOf("dir" to ${dir}, "include" to listOf(${include}))))`;
@@ -529,68 +529,65 @@ function finalize(instance) {
529
529
  }
530
530
  }
531
531
  }
532
- if (upgrade || jvmTarget) {
533
- const compatibility = 'JavaVersion.VERSION_' + (upgrade ? javaVersion.toString().replace(/\./g, '_') : jvmTarget);
532
+ if (upgrade) {
533
+ const compatibility = 'JavaVersion.VERSION_' + javaVersion.toString().replace(/\./g, '_');
534
+ const sourceCompat = valueFor('sourceCompatibility', compatibility, kotlin);
535
+ const targetCompat = valueFor('targetCompatibility', compatibility, kotlin);
534
536
  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);
537
+ output = Document.updateGradle(output, ['java'], sourceCompat, updateOpts(true));
538
+ if (output === source) {
539
+ output = Document.updateGradle(output, ['android', 'compileOptions'], sourceCompat, updateOpts());
540
+ output = Document.updateGradle(output, ['android', 'compileOptions'], targetCompat, updateOpts());
539
541
  }
540
542
  else {
541
- output = Document.updateGradle(output, ['android', 'compileOptions'], 'sourceCompatibility ' + compatibility, upgrade);
542
- output = Document.updateGradle(output, ['android', 'compileOptions'], 'targetCompatibility ' + compatibility, upgrade);
543
+ output = Document.updateGradle(output, ['java'], targetCompat, updateOpts(true));
543
544
  }
544
545
  setModified(output);
545
546
  }
546
547
  if (jvmToolchain) {
547
548
  let output = source;
548
549
  if (language === 'java') {
549
- output = Document.updateGradle(output, ['java', 'toolchain'], kotlin ? `languageVersion.set(JavaLanguageVersion.of(${jvmToolchain}))` : `languageVersion = JavaLanguageVersion.of(${jvmToolchain})`, true);
550
+ output = Document.updateGradle(output, ['java', 'toolchain'], kotlin ? `languageVersion.set(JavaLanguageVersion.of(${jvmToolchain}))` : `languageVersion = JavaLanguageVersion.of(${jvmToolchain})`, updateOpts());
550
551
  }
551
552
  else {
552
- output = Document.updateGradle(output, ['kotlin'], kotlin ? `jvmToolchain(${jvmToolchain})` : 'jvmToolchain ' + jvmToolchain, true);
553
+ output = Document.updateGradle(output, ['kotlin'], kotlin ? `jvmToolchain(${jvmToolchain})` : 'jvmToolchain ' + jvmToolchain, updateOpts());
553
554
  }
554
555
  setModified(output);
555
556
  }
556
- if (!existing) {
557
- const targetAPI = instance.targetAPI;
557
+ if (targetAPI) {
558
558
  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);
559
+ const tryInline = (compileSdk) => {
560
+ output = Document.updateGradle(output, ['android'], valueFor('compileSdk', compileSdk, kotlin), updateOpts(true));
561
+ return output !== source;
562
+ };
563
+ if (typeof targetAPI === 'number') {
564
+ const targetMajor = Math.floor(targetAPI);
565
+ output = Document.updateGradle(output, ['android', /version\s*=?\s*(release\(\d+\))/], [`release(${targetMajor})`, valueFor('minorApiLevel', Math.trunc((targetAPI - targetMajor) * 10), true)], updateOpts(true));
566
+ if (output === source) {
567
+ tryInline(targetMajor);
578
568
  }
579
569
  }
580
- if (applicationId) {
581
- output = Document.updateGradle(output, ['android', 'defaultConfig'], (kotlin ? 'applicationId = ' : 'applicationId ') + `"${applicationId}"`, true);
570
+ else if (tryInline(`"android-${targetAPI}"`)) {
571
+ output = Document.updateGradle(output, ['android', 'defaultConfig'], valueFor('targetSdk', targetAPI, kotlin, true), updateOpts());
572
+ }
573
+ const version = instance.findVersion('buildToolsVersion');
574
+ if (version) {
575
+ output = Document.updateGradle(output, ['android'], valueFor('buildToolsVersion', version, kotlin, true), updateOpts());
582
576
  }
583
577
  setModified(output);
584
578
  }
579
+ if (applicationId) {
580
+ setModified(Document.updateGradle(source, ['android', 'defaultConfig'], valueFor('applicationId', applicationId, kotlin, true), updateOpts()));
581
+ }
585
582
  if (dataBinding) {
586
- setModified(Document.updateGradle(source, ['android', 'buildFeatures'], kotlin ? 'dataBinding = true' : 'dataBinding true', true));
583
+ setModified(Document.updateGradle(source, ['android', 'buildFeatures'], valueFor('dataBinding', 'true', true), updateOpts()));
587
584
  }
588
585
  if (namespace) {
589
- setModified(Document.updateGradle(source, ['android'], (kotlin ? 'namespace = ' : 'namespace ') + `"${namespace}"`, true));
586
+ setModified(Document.updateGradle(source, ['android'], valueFor('namespace', namespace, true, true), updateOpts()));
590
587
  }
591
588
  if (profileable) {
592
589
  let name, items;
593
- if ((0, types_1.isArray)(profileable)) {
590
+ if (isArray(profileable)) {
594
591
  name = profileable[0];
595
592
  if (typeof name === 'string' && !name.startsWith('--')) {
596
593
  items = profileable.slice(1);
@@ -609,17 +606,17 @@ function finalize(instance) {
609
606
  }
610
607
  }
611
608
  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)) {
609
+ setModified(Document.updateGradle(source, ['android', 'buildTypes', kotlin ? 'getByName("release")' : 'release'], 'signingConfig ' + (kotlin ? `= signingConfigs.getByName("${name}")` : 'signingConfigs.' + name), updateOpts()));
610
+ if (isArray(items)) {
614
611
  const parameters = items.map(value => `"${value}"`).join(', ');
615
- setModified(Document.updateGradle(source, ['android', 'aaptOptions'], 'additionalParameters ' + (kotlin ? `= [${parameters}]` : parameters), true));
612
+ setModified(Document.updateGradle(source, ['android', 'aaptOptions'], 'additionalParameters ' + (kotlin ? `= [${parameters}]` : parameters), updateOpts()));
616
613
  }
617
614
  }
618
615
  if (versionName) {
619
- setModified(Document.updateGradle(source, ['android', 'defaultConfig'], (kotlin ? 'versionName = ' : 'versionName ') + `"${versionName}"`, true));
616
+ setModified(Document.updateGradle(source, ['android', 'defaultConfig'], valueFor('versionName', versionName, kotlin, true), updateOpts()));
620
617
  }
621
618
  if (versionCode) {
622
- setModified(Document.updateGradle(source, ['android', 'defaultConfig'], (kotlin ? 'versionCode = ' : 'versionCode ') + versionCode, true));
619
+ setModified(Document.updateGradle(source, ['android', 'defaultConfig'], valueFor('versionCode', versionCode, kotlin), updateOpts()));
623
620
  }
624
621
  if (modified || !existing) {
625
622
  try {
@@ -678,4 +675,5 @@ function finalize(instance) {
678
675
  }
679
676
  }
680
677
  }
678
+
681
679
  module.exports = finalize;