@laurence79/wireit 0.14.13-shared-cache.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.
- package/LICENSE +202 -0
- package/README.md +1062 -0
- package/bin/wireit.js +9 -0
- package/lib/analyzer.js +1600 -0
- package/lib/caching/cache.js +7 -0
- package/lib/caching/github-actions-cache.js +832 -0
- package/lib/caching/local-cache.js +78 -0
- package/lib/caching/shared-cache.js +256 -0
- package/lib/cli-options.js +495 -0
- package/lib/cli.js +177 -0
- package/lib/config.js +18 -0
- package/lib/error.js +160 -0
- package/lib/event.js +7 -0
- package/lib/execution/base.js +108 -0
- package/lib/execution/no-command.js +32 -0
- package/lib/execution/service.js +1017 -0
- package/lib/execution/standard.js +683 -0
- package/lib/executor.js +249 -0
- package/lib/fingerprint.js +164 -0
- package/lib/ide.js +583 -0
- package/lib/language-server.js +135 -0
- package/lib/logging/combination-logger.js +41 -0
- package/lib/logging/debug-logger.js +43 -0
- package/lib/logging/logger.js +38 -0
- package/lib/logging/metrics-logger.js +108 -0
- package/lib/logging/quiet/run-tracker.js +597 -0
- package/lib/logging/quiet/stack-map.js +41 -0
- package/lib/logging/quiet/writeover-line.js +197 -0
- package/lib/logging/quiet-logger.js +78 -0
- package/lib/logging/simple-logger.js +296 -0
- package/lib/logging/watch-logger.js +81 -0
- package/lib/script-child-process.js +270 -0
- package/lib/util/ast.js +71 -0
- package/lib/util/async-cache.js +24 -0
- package/lib/util/copy.js +120 -0
- package/lib/util/deferred.js +35 -0
- package/lib/util/delete.js +120 -0
- package/lib/util/dispose.js +16 -0
- package/lib/util/fs.js +258 -0
- package/lib/util/glob.js +255 -0
- package/lib/util/line-monitor.js +69 -0
- package/lib/util/manifest.js +31 -0
- package/lib/util/optimize-mkdirs.js +55 -0
- package/lib/util/package-json-reader.js +61 -0
- package/lib/util/package-json.js +179 -0
- package/lib/util/script-data-dir.js +19 -0
- package/lib/util/shuffle.js +16 -0
- package/lib/util/unreachable.js +12 -0
- package/lib/util/windows.js +87 -0
- package/lib/util/worker-pool.js +61 -0
- package/lib/watcher.js +396 -0
- package/package.json +470 -0
- package/schema.json +132 -0
- package/wireit.svg +1 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
// This is where the bulk of the work of the extension happens. This file
|
|
7
|
+
// runs in its own process, and communicates with the main process via
|
|
8
|
+
// node IPC.
|
|
9
|
+
// jsonc-parser often uses 'any' when they mean 'unknown'. We might want to
|
|
10
|
+
// declare our own types for them, but for now, we'll just quiet down eslint.
|
|
11
|
+
import { createConnection, TextDocuments, ProposedFeatures, TextDocumentSyncKind, CodeActionKind, } from 'vscode-languageserver/node';
|
|
12
|
+
import * as url from 'url';
|
|
13
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
14
|
+
import { inspect } from 'util';
|
|
15
|
+
import { IdeAnalyzer } from './ide.js';
|
|
16
|
+
const ideAnalyzer = new IdeAnalyzer();
|
|
17
|
+
const connection = createConnection(ProposedFeatures.all);
|
|
18
|
+
connection.onInitialize((init) => {
|
|
19
|
+
const workspacePaths = [];
|
|
20
|
+
for (const folder of init.workspaceFolders ?? []) {
|
|
21
|
+
workspacePaths.push(url.fileURLToPath(folder.uri));
|
|
22
|
+
}
|
|
23
|
+
ideAnalyzer.setWorkspaceRoots(workspacePaths);
|
|
24
|
+
const result = {
|
|
25
|
+
capabilities: {
|
|
26
|
+
textDocumentSync: TextDocumentSyncKind.Incremental,
|
|
27
|
+
// If we add any new features, we'll generally need to declare them
|
|
28
|
+
// here.
|
|
29
|
+
codeActionProvider: {
|
|
30
|
+
codeActionKinds: [
|
|
31
|
+
CodeActionKind.QuickFix,
|
|
32
|
+
CodeActionKind.RefactorExtract,
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
definitionProvider: true,
|
|
36
|
+
referencesProvider: true,
|
|
37
|
+
completionProvider: {
|
|
38
|
+
// We don't have more information later, so don't bother asking.
|
|
39
|
+
resolveProvider: false,
|
|
40
|
+
completionItem: {},
|
|
41
|
+
triggerCharacters: ['"', ':', '/'],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
return result;
|
|
46
|
+
});
|
|
47
|
+
function log(...values) {
|
|
48
|
+
for (const value of values) {
|
|
49
|
+
let message;
|
|
50
|
+
if (typeof value === 'string') {
|
|
51
|
+
message = value;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
message = inspect(value, { depth: 4 });
|
|
55
|
+
}
|
|
56
|
+
connection.console.log(message);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// So that we can just console.log and console.error as usual.
|
|
60
|
+
console.log = log;
|
|
61
|
+
console.error = log;
|
|
62
|
+
const documents = new TextDocuments(TextDocument);
|
|
63
|
+
let requestIdCounter = 0;
|
|
64
|
+
const getAndSendDiagnostics = async () => {
|
|
65
|
+
requestIdCounter++;
|
|
66
|
+
const requestId = requestIdCounter;
|
|
67
|
+
const diagnosticsByFile = await ideAnalyzer.getDiagnostics();
|
|
68
|
+
if (requestId !== requestIdCounter) {
|
|
69
|
+
return; // another request has been made since this one
|
|
70
|
+
}
|
|
71
|
+
for (const path of ideAnalyzer.openFiles) {
|
|
72
|
+
const diagnostics = diagnosticsByFile.get(path) ?? [];
|
|
73
|
+
void connection.sendDiagnostics({
|
|
74
|
+
uri: url.pathToFileURL(path).toString(),
|
|
75
|
+
diagnostics: [...diagnostics],
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const updateOpenFile = (document) => {
|
|
80
|
+
if (document.languageId !== 'json') {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const path = url.fileURLToPath(document.uri);
|
|
84
|
+
if (!path.endsWith('package.json')) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const contents = document.getText();
|
|
88
|
+
ideAnalyzer.setOpenFileContents(path, contents);
|
|
89
|
+
void getAndSendDiagnostics();
|
|
90
|
+
};
|
|
91
|
+
documents.onDidOpen((event) => {
|
|
92
|
+
updateOpenFile(event.document);
|
|
93
|
+
});
|
|
94
|
+
documents.onDidChangeContent((change) => {
|
|
95
|
+
updateOpenFile(change.document);
|
|
96
|
+
});
|
|
97
|
+
documents.onDidClose((change) => {
|
|
98
|
+
const path = url.fileURLToPath(change.document.uri);
|
|
99
|
+
ideAnalyzer.closeFile(path);
|
|
100
|
+
void getAndSendDiagnostics();
|
|
101
|
+
// Clear diagnostics for closed file.
|
|
102
|
+
void connection.sendDiagnostics({
|
|
103
|
+
uri: change.document.uri,
|
|
104
|
+
diagnostics: [],
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
connection.onCodeAction(async (params) => {
|
|
108
|
+
const document = documents.get(params.textDocument.uri);
|
|
109
|
+
if (document === undefined) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
const path = url.fileURLToPath(document.uri);
|
|
113
|
+
const actions = await ideAnalyzer.getCodeActions(path, params.range);
|
|
114
|
+
return actions;
|
|
115
|
+
});
|
|
116
|
+
connection.onDefinition(async (params) => {
|
|
117
|
+
const path = url.fileURLToPath(params.textDocument.uri);
|
|
118
|
+
const position = params.position;
|
|
119
|
+
return ideAnalyzer.getDefinition(path, position);
|
|
120
|
+
});
|
|
121
|
+
connection.onReferences(async (params) => {
|
|
122
|
+
// TODO: handle params.context.includeDeclaration
|
|
123
|
+
const path = url.fileURLToPath(params.textDocument.uri);
|
|
124
|
+
const position = params.position;
|
|
125
|
+
return ideAnalyzer.findAllReferences(path, position);
|
|
126
|
+
});
|
|
127
|
+
connection.onCompletion(async (params) => {
|
|
128
|
+
const path = url.fileURLToPath(params.textDocument.uri);
|
|
129
|
+
const position = params.position;
|
|
130
|
+
return ideAnalyzer.getCompletions(path, position);
|
|
131
|
+
});
|
|
132
|
+
// Actually start listening
|
|
133
|
+
documents.listen(connection);
|
|
134
|
+
connection.listen();
|
|
135
|
+
//# sourceMappingURL=language-server.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
// To prevent using the global console accidentally, we shadow it with
|
|
7
|
+
// undefined
|
|
8
|
+
const console = undefined;
|
|
9
|
+
function markAsUsed(_) { }
|
|
10
|
+
markAsUsed(console);
|
|
11
|
+
/**
|
|
12
|
+
* A {@link Logger} that logs to multiple loggers.
|
|
13
|
+
*/
|
|
14
|
+
export class CombinationLogger {
|
|
15
|
+
#loggers;
|
|
16
|
+
constructor(loggers, console) {
|
|
17
|
+
this.console = console;
|
|
18
|
+
this.#loggers = loggers;
|
|
19
|
+
}
|
|
20
|
+
log(event) {
|
|
21
|
+
for (const logger of this.#loggers) {
|
|
22
|
+
logger.log(event);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
printMetrics() {
|
|
26
|
+
for (const logger of this.#loggers) {
|
|
27
|
+
logger.printMetrics?.();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
getWatchLogger() {
|
|
31
|
+
const watchLoggers = this.#loggers.map((logger) => logger.getWatchLogger?.() ?? logger);
|
|
32
|
+
return new CombinationLogger(watchLoggers, this.console);
|
|
33
|
+
}
|
|
34
|
+
[Symbol.dispose]() {
|
|
35
|
+
for (const logger of this.#loggers) {
|
|
36
|
+
logger[Symbol.dispose]?.();
|
|
37
|
+
}
|
|
38
|
+
this.console[Symbol.dispose]();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=combination-logger.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { SimpleLogger } from './simple-logger.js';
|
|
7
|
+
import { inspect } from 'node:util';
|
|
8
|
+
// To prevent using the global console accidentally, we shadow it with
|
|
9
|
+
// undefined
|
|
10
|
+
const console = undefined;
|
|
11
|
+
function markAsUsed(_) { }
|
|
12
|
+
markAsUsed(console);
|
|
13
|
+
/**
|
|
14
|
+
* A {@link Logger} for logging debug information, mainly in tests.
|
|
15
|
+
*/
|
|
16
|
+
export class DebugLogger extends SimpleLogger {
|
|
17
|
+
log(event) {
|
|
18
|
+
switch (event.type) {
|
|
19
|
+
case 'info':
|
|
20
|
+
this.console.log(`<info> ${event.detail}`);
|
|
21
|
+
break;
|
|
22
|
+
case 'failure':
|
|
23
|
+
this.console.log(`<failure> ${event.reason}`);
|
|
24
|
+
break;
|
|
25
|
+
case 'output':
|
|
26
|
+
// too verbose, log nothing
|
|
27
|
+
return;
|
|
28
|
+
case 'success':
|
|
29
|
+
this.console.log(`<success> ${event.reason}`);
|
|
30
|
+
break;
|
|
31
|
+
default: {
|
|
32
|
+
const never = event;
|
|
33
|
+
throw new Error(`Unknown event type: ${inspect(never)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
super.log(event);
|
|
37
|
+
}
|
|
38
|
+
[Symbol.dispose]() {
|
|
39
|
+
super[Symbol.dispose]();
|
|
40
|
+
this.console[Symbol.dispose]();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=debug-logger.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import '../util/dispose.js';
|
|
7
|
+
import { Console as NodeConsole } from 'node:console';
|
|
8
|
+
// To prevent using the global console accidentally, we shadow it with
|
|
9
|
+
// undefined
|
|
10
|
+
const console = undefined;
|
|
11
|
+
function markAsUsed(_) { }
|
|
12
|
+
markAsUsed(console);
|
|
13
|
+
export class Console extends NodeConsole {
|
|
14
|
+
#closeStreams;
|
|
15
|
+
#closed = false;
|
|
16
|
+
constructor(stdout, stderr, closeStreams = false) {
|
|
17
|
+
super(stdout, stderr);
|
|
18
|
+
this.stdout = stdout;
|
|
19
|
+
this.stderr = stderr;
|
|
20
|
+
this.#closeStreams = closeStreams;
|
|
21
|
+
}
|
|
22
|
+
[Symbol.dispose]() {
|
|
23
|
+
if (this.#closed) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.#closed = true;
|
|
27
|
+
if (this.#closeStreams) {
|
|
28
|
+
this.stdout.end();
|
|
29
|
+
this.stderr.end();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* When true, we're debugging the logger itself, so a logger should log with
|
|
35
|
+
* more verbosity, and not overwrite previously written lines.
|
|
36
|
+
*/
|
|
37
|
+
export const DEBUG = Boolean(process.env['WIREIT_DEBUG_LOGGER']);
|
|
38
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { hrtime } from 'process';
|
|
7
|
+
import { SimpleLogger } from './simple-logger.js';
|
|
8
|
+
// To prevent using the global console accidentally, we shadow it with
|
|
9
|
+
// undefined
|
|
10
|
+
const console = undefined;
|
|
11
|
+
function markAsUsed(_) { }
|
|
12
|
+
markAsUsed(console);
|
|
13
|
+
/**
|
|
14
|
+
* A {@link Logger} that keeps track of metrics.
|
|
15
|
+
*/
|
|
16
|
+
export class MetricsLogger extends SimpleLogger {
|
|
17
|
+
#startTime = hrtime();
|
|
18
|
+
#metrics = [
|
|
19
|
+
{
|
|
20
|
+
name: 'Success',
|
|
21
|
+
// 'no-command' is technically a success, but we don't want to count it as
|
|
22
|
+
// a success for this metric because nothing was actually run.
|
|
23
|
+
matches: (e) => e.type === 'success' && e.reason !== 'no-command',
|
|
24
|
+
count: 0,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Ran',
|
|
28
|
+
matches: (e) => e.type === 'success' && e.reason === 'exit-zero',
|
|
29
|
+
count: 0,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'Skipped (fresh)',
|
|
33
|
+
matches: (e) => e.type === 'success' && e.reason === 'fresh',
|
|
34
|
+
count: 0,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'Restored from cache',
|
|
38
|
+
matches: (e) => e.type === 'success' && e.reason === 'cached',
|
|
39
|
+
count: 0,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* @param rootPackage The npm package directory that the root script being
|
|
44
|
+
* executed belongs to.
|
|
45
|
+
*/
|
|
46
|
+
constructor(rootPackage, console) {
|
|
47
|
+
super(rootPackage, console);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Update relevant metrics for an event and pass it up to the parent logger.
|
|
51
|
+
*/
|
|
52
|
+
log(event) {
|
|
53
|
+
// When in watch mode, metrics should reset at the start of each run.
|
|
54
|
+
if (event.type === 'info' && event.detail === 'watch-run-start') {
|
|
55
|
+
this.#resetMetrics();
|
|
56
|
+
}
|
|
57
|
+
this.#updateMetrics(event);
|
|
58
|
+
super.log(event);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Log the current metrics and reset the state of each metric.
|
|
62
|
+
*/
|
|
63
|
+
printMetrics() {
|
|
64
|
+
const successes = this.#metrics[0].count ?? 0;
|
|
65
|
+
if (!successes) {
|
|
66
|
+
this.#resetMetrics();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const elapsed = this.#getElapsedTime();
|
|
70
|
+
const nameOffset = 20;
|
|
71
|
+
const out = [
|
|
72
|
+
`🏁 [metrics] Executed ${successes} script(s) in ${elapsed} seconds`,
|
|
73
|
+
];
|
|
74
|
+
for (const metric of this.#metrics.slice(1)) {
|
|
75
|
+
const name = metric.name.padEnd(nameOffset);
|
|
76
|
+
const count = metric.count;
|
|
77
|
+
const percent = this.#calculatePercentage(count, successes);
|
|
78
|
+
out.push(`\t${name}: ${count} (${percent}%)`);
|
|
79
|
+
}
|
|
80
|
+
this.console.log(out.join('\n'));
|
|
81
|
+
this.#resetMetrics();
|
|
82
|
+
}
|
|
83
|
+
#updateMetrics(event) {
|
|
84
|
+
for (const metric of this.#metrics) {
|
|
85
|
+
if (metric.matches(event)) {
|
|
86
|
+
metric.count++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
#resetMetrics() {
|
|
91
|
+
this.#startTime = hrtime();
|
|
92
|
+
for (const metric of this.#metrics) {
|
|
93
|
+
metric.count = 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
#getElapsedTime() {
|
|
97
|
+
const [seconds, nanoseconds] = hrtime(this.#startTime);
|
|
98
|
+
const time = seconds + nanoseconds / 1e9;
|
|
99
|
+
return time.toFixed(2);
|
|
100
|
+
}
|
|
101
|
+
#calculatePercentage(numerator, denominator) {
|
|
102
|
+
if (denominator === 0) {
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
return Math.floor((numerator / denominator) * 100);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=metrics-logger.js.map
|