Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/common/console.ts
3291 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { URI } from './uri.js';
7
8
export interface IRemoteConsoleLog {
9
type: string;
10
severity: string;
11
arguments: string;
12
}
13
14
export interface IStackArgument {
15
__$stack: string;
16
}
17
18
export interface IStackFrame {
19
uri: URI;
20
line: number;
21
column: number;
22
}
23
24
export function isRemoteConsoleLog(obj: unknown): obj is IRemoteConsoleLog {
25
const entry = obj as IRemoteConsoleLog;
26
27
return entry && typeof entry.type === 'string' && typeof entry.severity === 'string';
28
}
29
30
export function parse(entry: IRemoteConsoleLog): { args: any[]; stack?: string } {
31
const args: any[] = [];
32
let stack: string | undefined;
33
34
// Parse Entry
35
try {
36
const parsedArguments: any[] = JSON.parse(entry.arguments);
37
38
// Check for special stack entry as last entry
39
const stackArgument = parsedArguments[parsedArguments.length - 1] as IStackArgument;
40
if (stackArgument && stackArgument.__$stack) {
41
parsedArguments.pop(); // stack is handled specially
42
stack = stackArgument.__$stack;
43
}
44
45
args.push(...parsedArguments);
46
} catch (error) {
47
args.push('Unable to log remote console arguments', entry.arguments);
48
}
49
50
return { args, stack };
51
}
52
53
export function getFirstFrame(entry: IRemoteConsoleLog): IStackFrame | undefined;
54
export function getFirstFrame(stack: string | undefined): IStackFrame | undefined;
55
export function getFirstFrame(arg0: IRemoteConsoleLog | string | undefined): IStackFrame | undefined {
56
if (typeof arg0 !== 'string') {
57
return getFirstFrame(parse(arg0!).stack);
58
}
59
60
// Parse a source information out of the stack if we have one. Format can be:
61
// at vscode.commands.registerCommand (/Users/someone/Desktop/test-ts/out/src/extension.js:18:17)
62
// or
63
// at /Users/someone/Desktop/test-ts/out/src/extension.js:18:17
64
// or
65
// at c:\Users\someone\Desktop\end-js\extension.js:19:17
66
// or
67
// at e.$executeContributedCommand(c:\Users\someone\Desktop\end-js\extension.js:19:17)
68
const stack = arg0;
69
if (stack) {
70
const topFrame = findFirstFrame(stack);
71
72
// at [^\/]* => line starts with "at" followed by any character except '/' (to not capture unix paths too late)
73
// (?:(?:[a-zA-Z]+:)|(?:[\/])|(?:\\\\) => windows drive letter OR unix root OR unc root
74
// (?:.+) => simple pattern for the path, only works because of the line/col pattern after
75
// :(?:\d+):(?:\d+) => :line:column data
76
const matches = /at [^\/]*((?:(?:[a-zA-Z]+:)|(?:[\/])|(?:\\\\))(?:.+)):(\d+):(\d+)/.exec(topFrame || '');
77
if (matches && matches.length === 4) {
78
return {
79
uri: URI.file(matches[1]),
80
line: Number(matches[2]),
81
column: Number(matches[3])
82
};
83
}
84
}
85
86
return undefined;
87
}
88
89
function findFirstFrame(stack: string | undefined): string | undefined {
90
if (!stack) {
91
return stack;
92
}
93
94
const newlineIndex = stack.indexOf('\n');
95
if (newlineIndex === -1) {
96
return stack;
97
}
98
99
return stack.substring(0, newlineIndex);
100
}
101
102
export function log(entry: IRemoteConsoleLog, label: string): void {
103
const { args, stack } = parse(entry);
104
105
const isOneStringArg = typeof args[0] === 'string' && args.length === 1;
106
107
let topFrame = findFirstFrame(stack);
108
if (topFrame) {
109
topFrame = `(${topFrame.trim()})`;
110
}
111
112
let consoleArgs: string[] = [];
113
114
// First arg is a string
115
if (typeof args[0] === 'string') {
116
if (topFrame && isOneStringArg) {
117
consoleArgs = [`%c[${label}] %c${args[0]} %c${topFrame}`, color('blue'), color(''), color('grey')];
118
} else {
119
consoleArgs = [`%c[${label}] %c${args[0]}`, color('blue'), color(''), ...args.slice(1)];
120
}
121
}
122
123
// First arg is something else, just apply all
124
else {
125
consoleArgs = [`%c[${label}]%`, color('blue'), ...args];
126
}
127
128
// Stack: add to args unless already added
129
if (topFrame && !isOneStringArg) {
130
consoleArgs.push(topFrame);
131
}
132
133
// Log it
134
if (typeof (console as any)[entry.severity] !== 'function') {
135
throw new Error('Unknown console method');
136
}
137
(console as any)[entry.severity].apply(console, consoleArgs);
138
}
139
140
function color(color: string): string {
141
return `color: ${color}`;
142
}
143
144