1+ // Copyright 2024 The MathWorks, Inc.
2+
3+ import { FoldingRangeParams , TextDocuments , FoldingRange } from 'vscode-languageserver'
4+ import { TextDocument } from 'vscode-languageserver-textdocument'
5+ import { URI } from 'vscode-uri'
6+ import MatlabLifecycleManager from '../../lifecycle/MatlabLifecycleManager'
7+ import { MatlabConnection } from '../../lifecycle/MatlabCommunicationManager'
8+
9+
10+ class FoldingSupportProvider {
11+ private readonly REQUEST_CHANNEL = '/matlabls/foldDocument/request'
12+ private readonly RESPONSE_CHANNEL = '/matlabls/foldDocument/response'
13+
14+ async handleFoldingRangeRequest ( params : FoldingRangeParams , documentManager : TextDocuments < TextDocument > ) : Promise < FoldingRange [ ] | null > {
15+ const docToFold = documentManager . get ( params . textDocument . uri )
16+ if ( docToFold == null ) {
17+ return null
18+ }
19+
20+ const matlabConnection = await MatlabLifecycleManager . getMatlabConnection ( )
21+ const isMatlabAvailable = ( matlabConnection != null )
22+ const matlabRelease = MatlabLifecycleManager . getMatlabRelease ( )
23+
24+ // check for connection and release
25+ if ( ! isMatlabAvailable || ( matlabRelease == null ) || ( matlabRelease < 'R2024b' ) ) {
26+ return null
27+ }
28+
29+ const fileName = URI . parse ( docToFold . uri ) . fsPath
30+ const code = docToFold . getText ( )
31+
32+ const frArray = await this . getFoldingRangesFromMatlab ( code , fileName , matlabConnection )
33+
34+ const foldingRanges = this . processFoldingRanges ( frArray )
35+
36+ return foldingRanges ;
37+ }
38+
39+ /**
40+ * Gets folding ranges from MATLAB.
41+ *
42+ * @param code The code in the file
43+ * @param fileName The file's name
44+ * @param matlabConnection The connection to MATLAB
45+ * @returns An array of line numbers
46+ */
47+ private async getFoldingRangesFromMatlab ( code : string , fileName : string , matlabConnection : MatlabConnection ) : Promise < number [ ] > {
48+ return await new Promise < number [ ] > ( resolve => {
49+ const channelId = matlabConnection . getChannelId ( )
50+ const channel = `${ this . RESPONSE_CHANNEL } /${ channelId } `
51+ const responseSub = matlabConnection . subscribe ( channel , message => {
52+ matlabConnection . unsubscribe ( responseSub )
53+ resolve ( message as number [ ] )
54+ } )
55+
56+ matlabConnection . publish ( this . REQUEST_CHANNEL , {
57+ code,
58+ fileName,
59+ channelId
60+ } )
61+ } )
62+ }
63+
64+ /**
65+ * Processes folding range data from MATLAB.
66+ *
67+ * @param frArray An array of line numbers from MATLAB
68+ * @returns An array of FoldingRanges
69+ */
70+ private processFoldingRanges ( frArray : number [ ] ) : FoldingRange [ ] {
71+ let fRangeArray : FoldingRange [ ] = [ ]
72+
73+ for ( let i = 0 ; i < frArray . length ; i = i + 2 ) {
74+ let fRange = FoldingRange . create ( frArray [ i ] - 1 , frArray [ i + 1 ] - 1 )
75+ fRangeArray . push ( fRange )
76+ }
77+
78+ return fRangeArray
79+ }
80+ }
81+
82+ export default new FoldingSupportProvider ( )
0 commit comments