@@ -39,9 +39,9 @@ export class Tracer {
3939
4040 this . tracingConsent = new TracingConsentCache ( ctx . extensionContext . workspaceState )
4141
42- this . remoteWorkspaceDumpUrl = this . ctx . extensionConfig . get < string > ( 'remoteWorkspaceDumpUrl' )
43- this . remoteTracingUrl = this . ctx . extensionConfig . get < string > ( 'remoteTracingUrl' )
44- const maximumMessageSize = this . ctx . extensionConfig . get < number > ( 'tracing .maximumMessageSize' )
42+ this . remoteWorkspaceDumpUrl = this . ctx . extensionConfig . get < string > ( 'trace. remoteWorkspaceDumpUrl' )
43+ this . remoteTracingUrl = this . ctx . extensionConfig . get < string > ( 'trace. remoteTracingUrl' )
44+ const maximumMessageSize = this . ctx . extensionConfig . get < number > ( 'trace .maximumMessageSize' )
4545 this . maximumMessageSize = maximumMessageSize === undefined || maximumMessageSize < 0 ? 0 : maximumMessageSize | 0
4646
4747 this . machineId = ( ( ) => {
@@ -73,16 +73,17 @@ export class Tracer {
7373 this . sessionId = new Date ( ) . toISOString ( )
7474 }
7575
76- run ( ) : { lspOutputChannel ?: vscode . OutputChannel } {
76+ run ( ) : vscode . OutputChannel | undefined {
7777 const consentCommandDisposable = vscode . commands . registerCommand ( consentCommandName , ( ) => this . askForTracingConsent ( ) )
7878 if ( this . isTracingEnabled && this . tracingConsent . get ( ) === 'no-answer' ) this . askForTracingConsent ( )
7979 this . initializeAsyncWorkspaceDump ( )
80+
8081 const lspOutputChannel = this . createLspOutputChannel ( )
8182 const statusBarItem = this . createStatusBarItem ( )
8283 for ( const disposable of [ consentCommandDisposable , lspOutputChannel , statusBarItem ] ) {
8384 if ( disposable ) this . ctx . extensionContext . subscriptions . push ( disposable )
8485 }
85- return { lspOutputChannel }
86+ return lspOutputChannel
8687 }
8788
8889 private askForTracingConsent ( ) : void {
@@ -97,13 +98,12 @@ export class Tracer {
9798 }
9899
99100 private initializeAsyncWorkspaceDump ( ) {
100- if ( this . remoteWorkspaceDumpUrl === undefined ) return
101- // convince TS that this is a string
102- const definedUrl : string = this . remoteWorkspaceDumpUrl
101+ const url = this . remoteWorkspaceDumpUrl
102+ if ( url === undefined ) return
103103
104104 const doInitialize = ( ) => {
105105 try {
106- this . asyncUploadWorkspaceDump ( definedUrl )
106+ this . asyncUploadWorkspaceDump ( url )
107107 } catch ( err ) {
108108 this . logError ( 'error during workspace dump' , safeError ( err ) )
109109 }
@@ -144,14 +144,20 @@ export class Tracer {
144144 }
145145
146146 private createLspOutputChannel ( ) : vscode . OutputChannel | undefined {
147- if ( ! this . remoteTracingUrl ) return undefined
147+ if ( this . ctx . extensionConfig . get ( 'trace.server' ) === undefined ) {
148+ if ( this . remoteTracingUrl ) this . ctx . extensionOut . appendLine (
149+ 'error: tracing URL is set, but trace.server not - no remote tracing possible.'
150+ )
151+ return undefined
152+ }
148153
149- const localLspOutputChannel = vscode . window . createOutputChannel ( 'Dotty LSP Communication' )
154+ const lspOutputChannel = vscode . window . createOutputChannel ( 'Dotty LSP Communication' )
155+ if ( ! this . remoteTracingUrl ) return lspOutputChannel
150156 try {
151- return this . createRemoteLspOutputChannel ( this . remoteTracingUrl , localLspOutputChannel )
157+ return this . createRemoteLspOutputChannel ( this . remoteTracingUrl , lspOutputChannel )
152158 } catch ( err ) {
153159 this . logError ( 'error during remote output channel creation' , safeError ( err ) )
154- return localLspOutputChannel
160+ return lspOutputChannel
155161 }
156162 }
157163
@@ -225,7 +231,7 @@ export class Tracer {
225231 )
226232
227233 socket . onerror = ( event ) => {
228- this . logErrorWithoutNotifying (
234+ this . logError (
229235 'socket error' ,
230236 remoteTracingUrl ,
231237 new SafeJsonifier ( event , ( event ) => ( {
@@ -238,7 +244,7 @@ export class Tracer {
238244 }
239245
240246 socket . onclose = ( event ) => {
241- this . logErrorWithoutNotifying (
247+ this . logError (
242248 'socket closed' ,
243249 remoteTracingUrl ,
244250 new SafeJsonifier ( event , ( event ) => ( {
@@ -319,11 +325,12 @@ export class Tracer {
319325 }
320326 }
321327
322- private silenceErrors : boolean = false
323- private logErrorWithoutNotifying ( message : string , ...rest : any [ ] ) {
328+ private logError ( message : string , ...rest : any [ ] ) {
324329 const msg = `[Dotty LSP Tracer] ${ message } `
325- // unwrap SafeJsonifier, for some reason Electron logs the result
326- // of .toJSON, unlike browsers
330+ // in a browser, we'd be able to log a SafeJsonifier directly
331+ // and get an inspectable object in the console
332+ // unfortunately, Electron apparently uses .toJson if available,
333+ // so we need to manually unwrap SafeJsonifiers
327334 console . error ( msg , ...rest . map ( ( a ) => a instanceof SafeJsonifier ? a . value : a ) )
328335 function cautiousStringify ( a : any ) : string {
329336 try {
@@ -335,34 +342,22 @@ export class Tracer {
335342 }
336343 this . ctx . extensionOut . appendLine ( [ msg ] . concat ( rest . map ( cautiousStringify ) ) . join ( ' ' ) )
337344 }
338- private logError ( message : string , ...rest : any [ ] ) {
339- this . logErrorWithoutNotifying ( message , ...rest )
340- if ( ! this . silenceErrors ) {
341- vscode . window . showErrorMessage (
342- 'An error occured which prevents sending usage data to EPFL. ' +
343- 'Please copy the text from "Dotty Language Client" output (View > Output) and send it to your TA.' ,
344- 'Silence further errors'
345- ) . then ( ( result ) => {
346- if ( result !== undefined ) {
347- this . silenceErrors = true
348- }
349- } )
350- }
351- }
352345}
353346
354347function safeError ( e : Error ) : SafeJsonifier < Error > {
355348 return new SafeJsonifier ( e , ( e ) => e . toString ( ) )
356349}
357350
351+ /**
352+ * Wraps a value of type T so it's possible to safely pass it to JSON.stringify.
353+ *
354+ * Values with circular references (errors, for example) cause JSON.stringify to throw an exception
355+ */
358356class SafeJsonifier < T > {
359- value : T
360- valueToObject : ( t : T ) => { }
361-
362- constructor ( value : T , valueToObject : ( t : T ) => { } ) {
363- this . value = value
364- this . valueToObject = valueToObject
365- }
357+ constructor (
358+ readonly value : T ,
359+ readonly valueToObject : ( t : T ) => { }
360+ ) { }
366361
367362 toJSON ( ) {
368363 return this . valueToObject ( this . value )
0 commit comments