@@ -18,59 +18,94 @@ import * as vscode from "vscode";
18
18
import { tmpdir } from "os" ;
19
19
import { exec } from "child_process" ;
20
20
import { Writable } from "stream" ;
21
- import { SwiftOutputChannel } from "../ui/SwiftOutputChannel" ;
22
21
import { WorkspaceContext } from "../WorkspaceContext" ;
23
22
import { Version } from "../utilities/version" ;
24
23
import { execFileStreamOutput } from "../utilities/utilities" ;
25
24
import configuration from "../configuration" ;
26
25
27
26
export async function captureDiagnostics ( ctx : WorkspaceContext ) {
28
- const diagnosticsDir = path . join (
29
- tmpdir ( ) ,
30
- `vscode-diagnostics-${ formatDateString ( new Date ( ) ) } `
31
- ) ;
32
-
33
27
try {
34
- await fs . mkdir ( diagnosticsDir ) ;
35
- await writeLogFile ( diagnosticsDir , "logs.txt" , extensionLogs ( ctx ) ) ;
36
- await writeLogFile ( diagnosticsDir , "environment.txt" , environmentLogs ( ctx ) ) ;
37
-
38
- if ( ctx . swiftVersion . isGreaterThanOrEqual ( new Version ( 6 , 0 , 0 ) ) ) {
39
- // sourcekit-lsp diagnose command is only available in 6.0 and higher.
40
- // await writeLogFile(diagnosticsDir, "sourcekit-lsp.txt", );
41
- await sourcekitDiagnose ( ctx , diagnosticsDir ) ;
42
- } else {
43
- await writeLogFile ( diagnosticsDir , "sourcekit-lsp.txt" , sourceKitLogs ( ctx ) ) ;
44
- }
28
+ const captureMode = await captureDiagnosticsMode ( ctx ) ;
45
29
46
- await writeLogFile ( diagnosticsDir , "diagnostics.txt" , diagnosticLogs ( ) ) ;
30
+ const diagnosticsDir = path . join (
31
+ tmpdir ( ) ,
32
+ `vscode-diagnostics-${ formatDateString ( new Date ( ) ) } `
33
+ ) ;
47
34
48
- ctx . outputChannel . log ( `Saved diagnostics to ${ diagnosticsDir } ` ) ;
35
+ await fs . mkdir ( diagnosticsDir ) ;
36
+ await writeLogFile ( diagnosticsDir , "extension-logs.txt" , extensionLogs ( ctx ) ) ;
37
+ await writeLogFile ( diagnosticsDir , "environment-logs.txt" , environmentLogs ( ctx ) ) ;
38
+ await writeLogFile ( diagnosticsDir , "diagnostics.txt" , diagnosticLogs ( ) ) ;
49
39
50
- const showInFinderButton = `Show In ${ showCommandType ( ) } ` ;
51
- const copyPath = "Copy Path to Clipboard" ;
52
- const result = await vscode . window . showInformationMessage (
53
- `Saved diagnostic logs to ${ diagnosticsDir } ` ,
54
- showInFinderButton ,
55
- copyPath
56
- ) ;
57
- if ( result === copyPath ) {
58
- vscode . env . clipboard . writeText ( diagnosticsDir ) ;
59
- } else if ( result === showInFinderButton ) {
60
- exec ( showDirectoryCommand ( diagnosticsDir ) , error => {
61
- // Opening the explorer on windows returns an exit code of 1 despite opening successfully.
62
- if ( error && process . platform !== "win32" ) {
63
- vscode . window . showErrorMessage (
64
- `Failed to open ${ showCommandType ( ) } : ${ error . message } `
65
- ) ;
66
- }
67
- } ) ;
40
+ if ( captureMode === "Full" ) {
41
+ // The `sourcekit-lsp diagnose` command is only available in 6.0 and higher.
42
+ if ( ctx . swiftVersion . isGreaterThanOrEqual ( new Version ( 6 , 0 , 0 ) ) ) {
43
+ await sourcekitDiagnose ( ctx , diagnosticsDir ) ;
44
+ } else {
45
+ await writeLogFile ( diagnosticsDir , "sourcekit-lsp.txt" , sourceKitLogs ( ctx ) ) ;
46
+ }
68
47
}
48
+
49
+ ctx . outputChannel . log ( `Saved diagnostics to ${ diagnosticsDir } ` ) ;
50
+ await showCapturedDiagnosticsResults ( diagnosticsDir ) ;
69
51
} catch ( error ) {
70
52
vscode . window . showErrorMessage ( `Unable to capture diagnostic logs: ${ error } ` ) ;
71
53
}
72
54
}
73
55
56
+ async function captureDiagnosticsMode ( ctx : WorkspaceContext ) : Promise < "Minimal" | "Full" > {
57
+ if (
58
+ ctx . swiftVersion . isGreaterThanOrEqual ( new Version ( 6 , 0 , 0 ) ) ||
59
+ vscode . workspace . getConfiguration ( "sourcekit-lsp" ) . get < string > ( "trace.server" , "off" ) !==
60
+ "off"
61
+ ) {
62
+ const fullButton = "Capture Full Diagnostics" ;
63
+ const minimalButton = "Capture Minimal Diagnostics" ;
64
+ const fullCaptureResult = await vscode . window . showInformationMessage (
65
+ `A Diagnostic Bundle collects information that helps the developers of the VS Code Swift extension diagnose and fix issues.
66
+
67
+ This information contains:
68
+ - Extension logs
69
+ - Versions of Swift installed on your system
70
+ - Crash logs from SourceKit
71
+ - Log messages emitted by SourceKit
72
+ - If possible, a minimized project that caused SourceKit to crash
73
+ - If possible, a minimized project that caused the Swift compiler to crash` ,
74
+ {
75
+ modal : true ,
76
+ detail : `If you wish to omit potentially sensitive information choose "${ minimalButton } "` ,
77
+ } ,
78
+ fullButton ,
79
+ minimalButton
80
+ ) ;
81
+ return fullCaptureResult === fullButton ? "Full" : "Minimal" ;
82
+ } else {
83
+ return "Minimal" ;
84
+ }
85
+ }
86
+
87
+ async function showCapturedDiagnosticsResults ( diagnosticsDir : string ) {
88
+ const showInFinderButton = `Show In ${ showCommandType ( ) } ` ;
89
+ const copyPath = "Copy Path to Clipboard" ;
90
+ const result = await vscode . window . showInformationMessage (
91
+ `Saved diagnostic logs to ${ diagnosticsDir } ` ,
92
+ showInFinderButton ,
93
+ copyPath
94
+ ) ;
95
+ if ( result === copyPath ) {
96
+ vscode . env . clipboard . writeText ( diagnosticsDir ) ;
97
+ } else if ( result === showInFinderButton ) {
98
+ exec ( showDirectoryCommand ( diagnosticsDir ) , error => {
99
+ // Opening the explorer on windows returns an exit code of 1 despite opening successfully.
100
+ if ( error && process . platform !== "win32" ) {
101
+ vscode . window . showErrorMessage (
102
+ `Failed to open ${ showCommandType ( ) } : ${ error . message } `
103
+ ) ;
104
+ }
105
+ } ) ;
106
+ }
107
+ }
108
+
74
109
async function writeLogFile ( dir : string , name : string , logs : string ) {
75
110
if ( logs . length === 0 ) {
76
111
return ;
@@ -83,13 +118,7 @@ function extensionLogs(ctx: WorkspaceContext): string {
83
118
}
84
119
85
120
function environmentLogs ( ctx : WorkspaceContext ) : string {
86
- const environmentOutputChannel = new SwiftOutputChannel ( "Swift" , false ) ;
87
- ctx . toolchain . logDiagnostics ( environmentOutputChannel ) ;
88
- environmentOutputChannel . log ( "Extension Settings:" ) ;
89
- environmentOutputChannel . log (
90
- JSON . stringify ( vscode . workspace . getConfiguration ( "swift" ) , null , 2 )
91
- ) ;
92
- return environmentOutputChannel . logs . join ( "\n" ) ;
121
+ return ctx . toolchain . diagnostics ;
93
122
}
94
123
95
124
function diagnosticLogs ( ) : string {
@@ -123,21 +152,28 @@ async function sourcekitDiagnose(ctx: WorkspaceContext, dir: string) {
123
152
location : vscode . ProgressLocation . Notification ,
124
153
} ,
125
154
async progress => {
126
- progress . report ( { message : "Capturing Diagnostics ..." } ) ;
155
+ progress . report ( { message : "Generating Diagnostic Bundle ..." } ) ;
127
156
const writableStream = progressUpdatingWritable ( percent =>
128
- progress . report ( { message : `Capturing Diagnostics : ${ percent } %` } )
157
+ progress . report ( { message : `Generating Diagnostic Bundle : ${ percent } %` } )
129
158
) ;
130
159
131
160
await execFileStreamOutput (
132
161
serverPath ,
133
- [ "diagnose" , "--bundle-output-path" , sourcekitDiagnosticDir ] ,
162
+ [
163
+ "diagnose" ,
164
+ "--bundle-output-path" ,
165
+ sourcekitDiagnosticDir ,
166
+ "--toolchain" ,
167
+ ctx . toolchain . toolchainPath ,
168
+ ] ,
134
169
writableStream ,
135
170
writableStream ,
136
171
null ,
137
172
{
138
173
env : { ...process . env , ...configuration . swiftEnvironmentVariables } ,
139
174
maxBuffer : 16 * 1024 * 1024 ,
140
- }
175
+ } ,
176
+ ctx . currentFolder ?? undefined
141
177
) ;
142
178
}
143
179
) ;
0 commit comments