1
1
import * as assert from 'assert'
2
2
import path from 'path'
3
- import { CallHierarchyIncomingCall , CallHierarchyItem , CallHierarchyOutgoingCall , CallHierarchyPrepareRequest , CancellationToken , CancellationTokenSource , CodeAction , CodeActionRequest , CodeLensRequest , Color , ColorInformation , ColorPresentation , CompletionItem , CompletionRequest , CompletionTriggerKind , ConfigurationRequest , DeclarationRequest , DefinitionRequest , DidChangeConfigurationNotification , DidChangeTextDocumentNotification , DidChangeWatchedFilesNotification , DidCloseTextDocumentNotification , DidCreateFilesNotification , DidDeleteFilesNotification , DidOpenTextDocumentNotification , DidRenameFilesNotification , DidSaveTextDocumentNotification , Disposable , DocumentColorRequest , DocumentDiagnosticReport , DocumentDiagnosticReportKind , DocumentDiagnosticRequest , DocumentFormattingRequest , DocumentHighlight , DocumentHighlightKind , DocumentHighlightRequest , DocumentLink , DocumentLinkRequest , DocumentOnTypeFormattingRequest , DocumentRangeFormattingRequest , DocumentSelector , DocumentSymbolRequest , FoldingRange , FoldingRangeRequest , FullDocumentDiagnosticReport , Hover , HoverRequest , ImplementationRequest , InlayHintKind , InlayHintLabelPart , InlayHintRequest , InlineValueEvaluatableExpression , InlineValueRequest , InlineValueText , InlineValueVariableLookup , LinkedEditingRangeRequest , Location , NotificationType0 , ParameterInformation , Position , ProgressToken , ProtocolRequestType , Range , ReferencesRequest , RenameRequest , SelectionRange , SelectionRangeRequest , SemanticTokensRegistrationType , SignatureHelpRequest , SignatureHelpTriggerKind , SignatureInformation , TextDocumentEdit , TextDocumentSyncKind , TextEdit , TypeDefinitionRequest , TypeHierarchyPrepareRequest , WillCreateFilesRequest , WillDeleteFilesRequest , WillRenameFilesRequest , WillSaveTextDocumentNotification , WillSaveTextDocumentWaitUntilRequest , WorkDoneProgressBegin , WorkDoneProgressCreateRequest , WorkDoneProgressEnd , WorkDoneProgressReport , WorkspaceEdit , WorkspaceSymbolRequest } from 'vscode-languageserver-protocol'
3
+ import { ApplyWorkspaceEditParams , CallHierarchyIncomingCall , CallHierarchyItem , CallHierarchyOutgoingCall , CallHierarchyPrepareRequest , CancellationToken , CancellationTokenSource , CodeAction , CodeActionRequest , CodeLensRequest , Color , ColorInformation , ColorPresentation , CompletionItem , CompletionRequest , CompletionTriggerKind , ConfigurationRequest , DeclarationRequest , DefinitionRequest , DidChangeConfigurationNotification , DidChangeTextDocumentNotification , DidChangeWatchedFilesNotification , DidCloseTextDocumentNotification , DidCreateFilesNotification , DidDeleteFilesNotification , DidOpenTextDocumentNotification , DidRenameFilesNotification , DidSaveTextDocumentNotification , Disposable , DocumentColorRequest , DocumentDiagnosticReport , DocumentDiagnosticReportKind , DocumentDiagnosticRequest , DocumentFormattingRequest , DocumentHighlight , DocumentHighlightKind , DocumentHighlightRequest , DocumentLink , DocumentLinkRequest , DocumentOnTypeFormattingRequest , DocumentRangeFormattingRequest , DocumentSelector , DocumentSymbolRequest , FoldingRange , FoldingRangeRequest , FullDocumentDiagnosticReport , Hover , HoverRequest , ImplementationRequest , InlayHintKind , InlayHintLabelPart , InlayHintRequest , InlineCompletionItem , InlineCompletionRequest , InlineValueEvaluatableExpression , InlineValueRequest , InlineValueText , InlineValueVariableLookup , LinkedEditingRangeRequest , Location , NotificationType0 , ParameterInformation , Position , ProgressToken , ProtocolRequestType , Range , ReferencesRequest , RenameRequest , SelectionRange , SelectionRangeRequest , SemanticTokensRegistrationType , SignatureHelpRequest , SignatureHelpTriggerKind , SignatureInformation , TextDocumentEdit , TextDocumentSyncKind , TextEdit , TypeDefinitionRequest , TypeHierarchyPrepareRequest , WillCreateFilesRequest , WillDeleteFilesRequest , WillRenameFilesRequest , WillSaveTextDocumentNotification , WillSaveTextDocumentWaitUntilRequest , WorkDoneProgressBegin , WorkDoneProgressCreateRequest , WorkDoneProgressEnd , WorkDoneProgressReport , WorkspaceEdit , WorkspaceSymbolRequest } from 'vscode-languageserver-protocol'
4
4
import { TextDocument } from 'vscode-languageserver-textdocument'
5
5
import { URI } from 'vscode-uri'
6
6
import commands from '../../commands'
@@ -101,7 +101,8 @@ describe('Client integration', () => {
101
101
102
102
middleware = { }
103
103
const clientOptions : LanguageClientOptions = {
104
- documentSelector, synchronize : { } , initializationOptions : { } , middleware
104
+ documentSelector, synchronize : { } , initializationOptions : { } , middleware,
105
+ workspaceFolder : { name : 'test_folder' , uri : URI . parse ( 'file-test:///' ) . toString ( ) } ,
105
106
}
106
107
107
108
client = new LanguageClient ( 'test svr' , 'Test Language Server' , serverOptions , clientOptions )
@@ -137,7 +138,9 @@ describe('Client integration', () => {
137
138
resolveProvider : true
138
139
} ,
139
140
documentFormattingProvider : true ,
140
- documentRangeFormattingProvider : true ,
141
+ documentRangeFormattingProvider : {
142
+ rangesSupport : true
143
+ } ,
141
144
documentOnTypeFormattingProvider : {
142
145
firstTriggerCharacter : ':'
143
146
} ,
@@ -154,6 +157,7 @@ describe('Client integration', () => {
154
157
documentSelector : [ { language : '*' } ]
155
158
} ,
156
159
selectionRangeProvider : true ,
160
+ inlineCompletionProvider : true ,
157
161
inlineValueProvider : { } ,
158
162
inlayHintProvider : {
159
163
resolveProvider : true
@@ -270,6 +274,7 @@ describe('Client integration', () => {
270
274
testFeature ( SemanticTokensRegistrationType . method , 'document' )
271
275
testFeature ( LinkedEditingRangeRequest . method , 'document' )
272
276
testFeature ( TypeHierarchyPrepareRequest . method , 'document' )
277
+ testFeature ( InlineCompletionRequest . method , 'document' )
273
278
testFeature ( InlineValueRequest . method , 'document' )
274
279
testFeature ( InlayHintRequest . method , 'document' )
275
280
testFeature ( WorkspaceSymbolRequest . method , 'workspace' )
@@ -538,6 +543,40 @@ describe('Client integration', () => {
538
543
)
539
544
} )
540
545
546
+ test ( 'Progress percentage is an integer' , async ( ) => {
547
+ const progressToken = 'TEST-PROGRESS-PERCENTAGE'
548
+ const percentages : Array < number | undefined > = [ ]
549
+ let currentProgressResolver : ( value : unknown ) => void | undefined
550
+
551
+ // Set up middleware that calls the current resolve function when it gets its 'end' progress event.
552
+ middleware . handleWorkDoneProgress = ( token : ProgressToken , params : WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd , next ) => {
553
+ if ( token === progressToken ) {
554
+ const percentage = params . kind === 'report' || params . kind === 'begin' ? params . percentage : undefined
555
+ percentages . push ( percentage )
556
+
557
+ if ( params . kind === 'end' ) {
558
+ setImmediate ( currentProgressResolver )
559
+ }
560
+ }
561
+ return next ( token , params )
562
+ }
563
+
564
+ // Trigger a progress event.
565
+ await new Promise < unknown > ( resolve => {
566
+ currentProgressResolver = resolve
567
+ void client . sendRequest (
568
+ new ProtocolRequestType < any , null , never , any , any > ( 'testing/sendPercentageProgress' ) ,
569
+ { } ,
570
+ tokenSource . token ,
571
+ )
572
+ } )
573
+
574
+ middleware . handleWorkDoneProgress = undefined
575
+
576
+ // Ensure percentages are rounded according to the spec
577
+ assert . deepStrictEqual ( percentages , [ 0 , 50 , undefined ] )
578
+ } )
579
+
541
580
test ( 'Document Formatting' , async ( ) => {
542
581
const provider = client . getFeature ( DocumentFormattingRequest . method ) . getProvider ( document )
543
582
isDefined ( provider )
@@ -822,7 +861,7 @@ describe('Client integration', () => {
822
861
823
862
const referenceFileUri = URI . parse ( '/dummy-edit' )
824
863
function ensureReferenceEdit ( edits : WorkspaceEdit , type : string , expectedLines : string [ ] ) {
825
- // // Ensure the edits are as expected.
864
+ // Ensure the edits are as expected.
826
865
assert . strictEqual ( edits . documentChanges ?. length , 1 )
827
866
const edit = edits . documentChanges [ 0 ] as TextDocumentEdit
828
867
assert . strictEqual ( edit . edits . length , 1 )
@@ -1351,6 +1390,27 @@ describe('Client integration', () => {
1351
1390
} , true )
1352
1391
} )
1353
1392
1393
+ test ( 'Inline Completions' , async ( ) => {
1394
+ const provider = client . getFeature ( InlineCompletionRequest . method ) ?. getProvider ( document )
1395
+ isDefined ( provider )
1396
+ const results = ( await provider . provideInlineCompletionItems ( document , position , { triggerKind : 1 , selectedCompletionInfo : { range, text : 'text' } } , tokenSource . token ) ) as InlineCompletionItem [ ]
1397
+
1398
+ isArray ( results , InlineCompletionItem , 1 )
1399
+
1400
+ rangeEqual ( results [ 0 ] . range ! , 1 , 2 , 3 , 4 )
1401
+ assert . strictEqual ( results [ 0 ] . filterText ! , 'te' )
1402
+ assert . strictEqual ( results [ 0 ] . insertText , 'text inline' )
1403
+
1404
+ let middlewareCalled = false
1405
+ middleware . provideInlineCompletionItems = ( d , r , c , t , n ) => {
1406
+ middlewareCalled = true
1407
+ return n ( d , r , c , t )
1408
+ }
1409
+ await provider . provideInlineCompletionItems ( document , position , { triggerKind : 1 , selectedCompletionInfo : undefined } , tokenSource . token )
1410
+ middleware . provideInlineCompletionItems = undefined
1411
+ assert . strictEqual ( middlewareCalled , true )
1412
+ } )
1413
+
1354
1414
test ( 'Workspace symbols' , async ( ) => {
1355
1415
const providers = client . getFeature ( WorkspaceSymbolRequest . method ) . getProviders ( )
1356
1416
isDefined ( providers )
@@ -1365,6 +1425,58 @@ describe('Client integration', () => {
1365
1425
isDefined ( symbol )
1366
1426
rangeEqual ( symbol . location [ 'range' ] , 1 , 2 , 3 , 4 )
1367
1427
} )
1428
+
1429
+ test ( 'General middleware' , async ( ) => {
1430
+ let middlewareCallCount = 0
1431
+ // Add a general middleware for both requests and notifications
1432
+ middleware . sendRequest = ( type , param , token , next ) => {
1433
+ middlewareCallCount ++
1434
+ return next ( type , param , token )
1435
+ }
1436
+ middleware . sendNotification = ( type , next , params ) => {
1437
+ middlewareCallCount ++
1438
+ return next ( type , params )
1439
+ }
1440
+ // Send a request
1441
+ const definitionProvider = client . getFeature ( DefinitionRequest . method ) . getProvider ( document )
1442
+ isDefined ( definitionProvider )
1443
+ await definitionProvider . provideDefinition ( document , position , tokenSource . token )
1444
+ // Send a notification
1445
+ const notificationProvider = client . getFeature ( DidSaveTextDocumentNotification . method ) . getProvider ( document )
1446
+ isDefined ( notificationProvider )
1447
+ await notificationProvider . send ( document )
1448
+ // Verify that both the request and notification went through the middleware
1449
+ middleware . sendRequest = undefined
1450
+ middleware . sendNotification = undefined
1451
+ assert . strictEqual ( middlewareCallCount , 2 )
1452
+ } )
1453
+
1454
+ test ( 'applyEdit middleware' , async ( ) => {
1455
+ const middlewareEvents : Array < ApplyWorkspaceEditParams > = [ ]
1456
+ let currentProgressResolver : ( value : unknown ) => void | undefined
1457
+
1458
+ middleware . workspace = middleware . workspace || { }
1459
+ middleware . workspace . handleApplyEdit = async ( params , next ) => {
1460
+ middlewareEvents . push ( params )
1461
+ setImmediate ( currentProgressResolver )
1462
+ return next ( params , tokenSource . token )
1463
+ }
1464
+
1465
+ // Trigger sample applyEdit event.
1466
+ await new Promise < unknown > ( resolve => {
1467
+ currentProgressResolver = resolve
1468
+ void client . sendRequest (
1469
+ new ProtocolRequestType < any , null , never , any , any > ( 'testing/sendApplyEdit' ) ,
1470
+ { } ,
1471
+ tokenSource . token ,
1472
+ )
1473
+ } )
1474
+
1475
+ middleware . workspace . handleApplyEdit = undefined
1476
+
1477
+ // Ensure event was handled.
1478
+ assert . deepStrictEqual ( middlewareEvents , [ { label : 'Apply Edit' , edit : { } } ] )
1479
+ } )
1368
1480
} )
1369
1481
1370
1482
namespace CrashNotification {
@@ -1383,9 +1495,9 @@ class CrashClient extends LanguageClient {
1383
1495
} )
1384
1496
}
1385
1497
1386
- protected handleConnectionClosed ( ) : void {
1387
- super . handleConnectionClosed ( )
1498
+ protected handleConnectionClosed ( ) : Promise < void > {
1388
1499
this . resolve ! ( )
1500
+ return super . handleConnectionClosed ( )
1389
1501
}
1390
1502
}
1391
1503
0 commit comments