carrick 0.3.91 → 0.3.93
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.
- package/README.md +7 -3
- package/bin/carrick.mjs +2 -2
- package/dist/auth/credentials.d.ts +1 -1
- package/dist/auth/credentials.js +1 -1
- package/dist/auth/credentials.js.map +1 -1
- package/dist/auth/oauth.d.ts +8 -0
- package/dist/auth/oauth.js +9 -1
- package/dist/auth/oauth.js.map +1 -1
- package/dist/auth/read.d.ts +5 -0
- package/dist/auth/read.js +11 -1
- package/dist/auth/read.js.map +1 -1
- package/dist/auth/run.d.ts +29 -1
- package/dist/auth/run.js +68 -9
- package/dist/auth/run.js.map +1 -1
- package/dist/init/connect.d.ts +19 -7
- package/dist/init/connect.js +29 -16
- package/dist/init/connect.js.map +1 -1
- package/dist/init/projects.d.ts +16 -3
- package/dist/init/projects.js +27 -18
- package/dist/init/projects.js.map +1 -1
- package/dist/init/remove.js +28 -5
- package/dist/init/remove.js.map +1 -1
- package/dist/init/repo-copies.d.ts +56 -0
- package/dist/init/repo-copies.js +241 -0
- package/dist/init/repo-copies.js.map +1 -0
- package/dist/init/repos.d.ts +27 -0
- package/dist/init/repos.js +67 -0
- package/dist/init/repos.js.map +1 -1
- package/dist/init/run.d.ts +109 -48
- package/dist/init/run.js +331 -154
- package/dist/init/run.js.map +1 -1
- package/dist/init/task-skills.d.ts +6 -6
- package/dist/init/task-skills.js +9 -9
- package/dist/init/task-skills.js.map +1 -1
- package/package.json +6 -6
- package/sidecar/dist/src/capture/check-probe.d.ts +6 -1
- package/sidecar/dist/src/capture/check-probe.js +7 -2
- package/sidecar/dist/src/capture/index.d.ts +1 -0
- package/sidecar/dist/src/capture/index.js +1 -0
- package/sidecar/dist/src/index.js +8 -2
- package/sidecar/dist/src/retype.d.ts +41 -4
- package/sidecar/dist/src/retype.js +82 -8
|
@@ -32,16 +32,19 @@ export class Retyper {
|
|
|
32
32
|
project;
|
|
33
33
|
inferrer;
|
|
34
34
|
jsonWire;
|
|
35
|
+
topTypes;
|
|
35
36
|
/**
|
|
36
37
|
* `jsonWire` is the check phase's own JSON wire transform
|
|
37
|
-
* (`jsonWireDeclarations` in the capture bundle)
|
|
38
|
-
*
|
|
39
|
-
* crossing the bundle
|
|
38
|
+
* (`jsonWireDeclarations` in the capture bundle) and `topTypes` its
|
|
39
|
+
* any/unknown walk, handed in by the entry point so both judges read the
|
|
40
|
+
* wire and a top type the same way without this file crossing the bundle
|
|
41
|
+
* seam.
|
|
40
42
|
*/
|
|
41
|
-
constructor(project, inferrer, jsonWire) {
|
|
43
|
+
constructor(project, inferrer, jsonWire, topTypes) {
|
|
42
44
|
this.project = project;
|
|
43
45
|
this.inferrer = inferrer;
|
|
44
46
|
this.jsonWire = jsonWire;
|
|
47
|
+
this.topTypes = topTypes;
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Judge every item, spending at most `budgetMs`. Each item rebuilds the
|
|
@@ -150,7 +153,8 @@ export class Retyper {
|
|
|
150
153
|
const text = stated(useWire);
|
|
151
154
|
const delta = text.length - (argEnd - argStart);
|
|
152
155
|
return {
|
|
153
|
-
edits: [{ start: argStart, end: argEnd, text }],
|
|
156
|
+
edits: [{ start: argStart, end: argEnd, text, statedAt: 0 }],
|
|
157
|
+
stated: text,
|
|
154
158
|
wire: useWire && wire,
|
|
155
159
|
typeArgumentCall: { start: callStart, end: callEnd + delta },
|
|
156
160
|
};
|
|
@@ -164,7 +168,8 @@ export class Retyper {
|
|
|
164
168
|
return (useWire) => {
|
|
165
169
|
const text = `<${stated(useWire)}>`;
|
|
166
170
|
return {
|
|
167
|
-
edits: [{ start: at, end: at, text }],
|
|
171
|
+
edits: [{ start: at, end: at, text, statedAt: 1 }],
|
|
172
|
+
stated: stated(useWire),
|
|
168
173
|
wire: useWire && wire,
|
|
169
174
|
typeArgumentCall: { start: callStart, end: callEnd + text.length },
|
|
170
175
|
};
|
|
@@ -190,6 +195,7 @@ export class Retyper {
|
|
|
190
195
|
const text = stated(useWire);
|
|
191
196
|
return {
|
|
192
197
|
edits: edits.flatMap((edit) => edit(text)),
|
|
198
|
+
stated: text,
|
|
193
199
|
wire: useWire && wire,
|
|
194
200
|
};
|
|
195
201
|
};
|
|
@@ -249,12 +255,76 @@ export class Retyper {
|
|
|
249
255
|
added.push(mapped);
|
|
250
256
|
}
|
|
251
257
|
added.sort((a, b) => a.start - b.start || a.code - b.code);
|
|
258
|
+
const unresolved = this.unresolvedMembers(sourceFile, rewrite, added.length > 0);
|
|
259
|
+
if (unresolved)
|
|
260
|
+
return { kind: 'abstain', reason: unresolved };
|
|
252
261
|
return { kind: 'checked', added };
|
|
253
262
|
}
|
|
254
263
|
finally {
|
|
255
264
|
sourceFile.replaceWithText(original);
|
|
256
265
|
}
|
|
257
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Why the stated type, as the consumer's program reads it, cannot be
|
|
269
|
+
* compared, or `undefined` when it can (carrick#1514). Read after the
|
|
270
|
+
* diagnostics diff, because the two top types fail in opposite directions.
|
|
271
|
+
*
|
|
272
|
+
* The producer's text is sent only when it holds no `any`/`unknown`, but
|
|
273
|
+
* the consumer's program is where it is read: under its compiler options,
|
|
274
|
+
* through the wire transform (a lib type whose `toJSON()` returns `any`),
|
|
275
|
+
* with its own declarations.
|
|
276
|
+
*
|
|
277
|
+
* - A member that reads as `unknown` makes reads fail that the producer's
|
|
278
|
+
* type would pass, so any diagnostic may be ours. It is never compared.
|
|
279
|
+
* - A member that reads as `any` can hide a failure but never make one, so
|
|
280
|
+
* the diagnostics the diff found stand; only an empty diff is not
|
|
281
|
+
* compared, since it may be the `any` agreeing.
|
|
282
|
+
*
|
|
283
|
+
* Either way the reason names the member, as the check phase does for a
|
|
284
|
+
* published type.
|
|
285
|
+
*
|
|
286
|
+
* The walk's budget sentinel is dropped. The scanner's text screen
|
|
287
|
+
* (`contains_disqualifying_top_type`, which has no budget) found no
|
|
288
|
+
* `any`/`unknown` in the producer's text before sending it, so a walk that
|
|
289
|
+
* runs out of budget can only miss one the consumer's program made deeper
|
|
290
|
+
* than the budget allows; the compiler's diagnostics stand.
|
|
291
|
+
*/
|
|
292
|
+
unresolvedMembers(sourceFile, rewrite, diagnosed) {
|
|
293
|
+
let shift = 0;
|
|
294
|
+
let at;
|
|
295
|
+
for (const edit of [...rewrite.edits].sort((a, b) => a.start - b.start)) {
|
|
296
|
+
if (at === undefined && edit.statedAt !== undefined) {
|
|
297
|
+
at = edit.start + shift + edit.statedAt;
|
|
298
|
+
}
|
|
299
|
+
shift += edit.text.length - (edit.end - edit.start);
|
|
300
|
+
}
|
|
301
|
+
const node = at === undefined
|
|
302
|
+
? undefined
|
|
303
|
+
: sourceFile.getDescendantAtStartWithWidth(at, rewrite.stated.length);
|
|
304
|
+
// Every rewrite states the type at a recorded offset, so this is only
|
|
305
|
+
// reached through a wrong offset; it abstains rather than skip the walk.
|
|
306
|
+
if (!node)
|
|
307
|
+
return 'the stated producer type could not be found again after the rewrite';
|
|
308
|
+
const type = node.getType().compilerType;
|
|
309
|
+
let found;
|
|
310
|
+
if (type.flags & ts.TypeFlags.Unknown)
|
|
311
|
+
found = [{ kind: 'unknown', path: '' }];
|
|
312
|
+
else if (type.flags & ts.TypeFlags.Any)
|
|
313
|
+
found = [{ kind: 'any', path: '' }];
|
|
314
|
+
else {
|
|
315
|
+
const program = this.project.getProgram().compilerObject;
|
|
316
|
+
found = this.topTypes(type, program, program.getTypeChecker(), node.compilerNode);
|
|
317
|
+
}
|
|
318
|
+
const unknowns = found.filter((finding) => finding.kind === 'unknown');
|
|
319
|
+
const anys = found.filter((finding) => finding.kind === 'any');
|
|
320
|
+
const deciding = unknowns.length > 0 ? unknowns : diagnosed ? [] : anys;
|
|
321
|
+
if (deciding.length === 0)
|
|
322
|
+
return undefined;
|
|
323
|
+
const members = deciding
|
|
324
|
+
.map(({ kind, path }) => (path === '' ? `'${kind}'` : `'${kind}' at '${path}'`))
|
|
325
|
+
.join(', ');
|
|
326
|
+
return `the producer's response reads as ${members} in the consumer's program, so it was not compared`;
|
|
327
|
+
}
|
|
258
328
|
/**
|
|
259
329
|
* The stated type argument must be what the call RETURNS (or a type
|
|
260
330
|
* argument or member of it): the rewrite is only a statement about the
|
|
@@ -738,7 +808,11 @@ function bodyReadEdit(read) {
|
|
|
738
808
|
const type = parent.getTypeNodeOrThrow();
|
|
739
809
|
const start = type.getStart();
|
|
740
810
|
const end = type.getEnd();
|
|
741
|
-
return (stated) => [
|
|
811
|
+
return (stated) => [
|
|
812
|
+
awaited
|
|
813
|
+
? { start, end, text: stated, statedAt: 0 }
|
|
814
|
+
: { start, end, text: `Promise<${stated}>`, statedAt: 'Promise<'.length },
|
|
815
|
+
];
|
|
742
816
|
}
|
|
743
817
|
else if (!Node.isParenthesizedExpression(parent))
|
|
744
818
|
break;
|
|
@@ -750,7 +824,7 @@ function bodyReadEdit(read) {
|
|
|
750
824
|
// The compiler reports past a parenthesis, so a finding on the cast read
|
|
751
825
|
// lands on `res`, an original position, never on this one.
|
|
752
826
|
{ start, end: start, text: '(' },
|
|
753
|
-
{ start: end, end, text: ` as Promise<${stated}>)
|
|
827
|
+
{ start: end, end, text: ` as Promise<${stated}>)`, statedAt: ' as Promise<'.length },
|
|
754
828
|
];
|
|
755
829
|
}
|
|
756
830
|
function declaresTypeParameters(call) {
|