Skip to content

Commit 08ec8bd

Browse files
authored
Merge pull request #46 from mathworks/dklilley.release-1.2.4
MATLAB language server - v1.2.4
2 parents 23d0854 + 97d43db commit 08ec8bd

24 files changed

+437
-292
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ MATLAB language server supports these editors by installing the corresponding ex
2727

2828
### Unreleased
2929

30+
### 1.2.4
31+
Release date: 2024-07-12
32+
33+
Added:
34+
* Improvements to code folding (requires MATLAB R2024b or later)
35+
36+
Fixed:
37+
* Allow connection to MATLAB when a single quote appears in the extension installation path
38+
* Resolve error with code navigation when using with MATLAB R2024b
39+
3040
### 1.2.3
3141
Release date: 2024-06-14
3242

matlab/+matlabls/+handlers/NavigationSupportHandler.m

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,19 @@ function handleResolvePathRequest (this, msg)
5353

5454
function path = resolvePath (name, contextFile)
5555
if isMATLABReleaseOlderThan('R2023b')
56-
% For usage in R2023b and earlier
56+
% For usage in R2023a and earlier
5757
[isFound, path] = matlabls.internal.resolvePath(name, contextFile);
5858
elseif isMATLABReleaseOlderThan('R2024a')
5959
% For usage in R2023b only
6060
[isFound, path] = matlab.internal.language.introspective.resolveFile(name, []);
61-
else
62-
% For usage in R2024a and later
61+
elseif isMATLABReleaseOlderThan('R2024b')
62+
% For usage in R2024a only
6363
ec = matlab.lang.internal.introspective.ExecutionContext;
6464
[isFound, path] = matlab.lang.internal.introspective.resolveFile(name, ec);
65+
else
66+
% For usage in R2024b and later
67+
ic = matlab.lang.internal.introspective.IntrospectiveContext.caller;
68+
[isFound, path] = matlab.lang.internal.introspective.resolveFile(name, ic);
6569
end
6670

6771
if ~isFound

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "matlab-language-server",
3-
"version": "1.2.3",
3+
"version": "1.2.4",
44
"description": "Language Server for MATLAB code",
55
"main": "./src/index.ts",
66
"bin": "./out/index.js",

src/ClientConnection.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2024 The MathWorks, Inc.
2+
import { _Connection, createConnection, ProposedFeatures } from "vscode-languageserver/node"
3+
4+
export type Connection = _Connection
5+
6+
export default class ClientConnection {
7+
private static connection: Connection
8+
9+
/**
10+
* Retrieves the connection to the client. If no connection currently exists,
11+
* a new connection is created.
12+
*
13+
* @returns The connection to the client
14+
*/
15+
public static getConnection (): Connection {
16+
if (ClientConnection.connection == null) {
17+
ClientConnection.connection = createConnection(ProposedFeatures.all)
18+
}
19+
20+
return ClientConnection.connection
21+
}
22+
23+
/**
24+
* Sets the ClientConnection to a given object.
25+
* This API is primarily meant for testing purposes.
26+
*
27+
* @param connection The connection object to set
28+
*/
29+
public static setConnection (connection: Connection): void {
30+
ClientConnection.connection = connection
31+
}
32+
}

src/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
// Copyright 2022 - 2023 The MathWorks, Inc.
1+
// Copyright 2022 - 2024 The MathWorks, Inc.
22

33
// Start up the LSP server
4-
import { connection } from './server'
4+
import ClientConnection from './ClientConnection'
5+
import * as server from './server'
56

6-
// Listen on the connection
7-
connection.listen()
7+
// Start up the language server
8+
server.startServer()
9+
10+
// Listen on the client connection
11+
ClientConnection.getConnection().listen()

src/indexing/DocumentIndexer.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ const INDEXING_DELAY = 500 // Delay (in ms) after keystroke before attempting to
1010
* Handles indexing a currently open document to gather data about classes,
1111
* functions, and variables.
1212
*/
13-
class DocumentIndexer {
13+
export default class DocumentIndexer {
1414
private readonly pendingFilesToIndex = new Map<string, NodeJS.Timeout>()
1515

16+
constructor (private indexer: Indexer) {}
17+
1618
/**
1719
* Queues a document to be indexed. This handles debouncing so that
1820
* indexing is not performed on every keystroke.
@@ -36,7 +38,7 @@ class DocumentIndexer {
3638
* @param textDocument The document being indexed
3739
*/
3840
indexDocument (textDocument: TextDocument): void {
39-
void Indexer.indexDocument(textDocument)
41+
void this.indexer.indexDocument(textDocument)
4042
}
4143

4244
/**
@@ -63,12 +65,10 @@ class DocumentIndexer {
6365
const uri = textDocument.uri
6466
if (this.pendingFilesToIndex.has(uri)) {
6567
this.clearTimerForDocumentUri(uri)
66-
await Indexer.indexDocument(textDocument)
68+
await this.indexer.indexDocument(textDocument)
6769
}
6870
if (!FileInfoIndex.codeDataCache.has(uri)) {
69-
await Indexer.indexDocument(textDocument)
71+
await this.indexer.indexDocument(textDocument)
7072
}
7173
}
7274
}
73-
74-
export default new DocumentIndexer()

src/indexing/FileInfoIndex.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ export enum FunctionVisibility {
9595
* Serves as an cache of data extracted from files
9696
*/
9797
class FileInfoIndex {
98+
private static instance: FileInfoIndex
99+
98100
/**
99101
* Maps document URI to the code data
100102
*/
@@ -105,6 +107,14 @@ class FileInfoIndex {
105107
*/
106108
readonly classInfoCache = new Map<string, MatlabClassInfo>()
107109

110+
public static getInstance (): FileInfoIndex {
111+
if (FileInfoIndex.instance == null) {
112+
FileInfoIndex.instance = new FileInfoIndex()
113+
}
114+
115+
return FileInfoIndex.instance
116+
}
117+
108118
/**
109119
* Parses the raw data into a more usable form. Caches the resulting data
110120
* in the code data index.
@@ -489,4 +499,4 @@ function convertRange (codeDataRange: CodeDataRange): Range {
489499
)
490500
}
491501

492-
export default new FileInfoIndex()
502+
export default FileInfoIndex.getInstance()

src/indexing/Indexer.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,22 @@ interface WorkspaceFileIndexedResponse {
1414
codeData: RawCodeData
1515
}
1616

17-
class Indexer {
17+
export default class Indexer {
1818
private readonly INDEX_DOCUMENT_REQUEST_CHANNEL = '/matlabls/indexDocument/request'
1919
private readonly INDEX_DOCUMENT_RESPONSE_CHANNEL = '/matlabls/indexDocument/response'
2020

2121
private readonly INDEX_FOLDERS_REQUEST_CHANNEL = '/matlabls/indexFolders/request'
2222
private readonly INDEX_FOLDERS_RESPONSE_CHANNEL = '/matlabls/indexFolders/response'
2323

24+
constructor (private matlabLifecycleManager: MatlabLifecycleManager, private pathResolver: PathResolver) {}
25+
2426
/**
2527
* Indexes the given TextDocument and caches the data.
2628
*
2729
* @param textDocument The document being indexed
2830
*/
2931
async indexDocument (textDocument: TextDocument): Promise<void> {
30-
const matlabConnection = await MatlabLifecycleManager.getMatlabConnection()
32+
const matlabConnection = await this.matlabLifecycleManager.getMatlabConnection()
3133

3234
if (matlabConnection == null) {
3335
return
@@ -46,7 +48,7 @@ class Indexer {
4648
* @param folders A list of folder URIs to be indexed
4749
*/
4850
async indexFolders (folders: string[]): Promise<void> {
49-
const matlabConnection = await MatlabLifecycleManager.getMatlabConnection()
51+
const matlabConnection = await this.matlabLifecycleManager.getMatlabConnection()
5052

5153
if (matlabConnection == null) {
5254
return
@@ -79,7 +81,7 @@ class Indexer {
7981
* @param uri The URI for the file being indexed
8082
*/
8183
async indexFile (uri: string): Promise<void> {
82-
const matlabConnection = await MatlabLifecycleManager.getMatlabConnection()
84+
const matlabConnection = await this.matlabLifecycleManager.getMatlabConnection()
8385

8486
if (matlabConnection == null) {
8587
return
@@ -143,7 +145,7 @@ class Indexer {
143145
// Find and queue indexing for parent classes
144146
const baseClasses = parsedCodeData.classInfo.baseClasses
145147

146-
const resolvedBaseClasses = await PathResolver.resolvePaths(baseClasses, uri, matlabConnection)
148+
const resolvedBaseClasses = await this.pathResolver.resolvePaths(baseClasses, uri, matlabConnection)
147149

148150
resolvedBaseClasses.forEach(resolvedBaseClass => {
149151
const uri = resolvedBaseClass.uri
@@ -153,5 +155,3 @@ class Indexer {
153155
})
154156
}
155157
}
156-
157-
export default new Indexer()

src/indexing/WorkspaceIndexer.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
// Copyright 2022 - 2023 The MathWorks, Inc.
1+
// Copyright 2022 - 2024 The MathWorks, Inc.
22

33
import { ClientCapabilities, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode-languageserver'
44
import ConfigurationManager from '../lifecycle/ConfigurationManager'
5-
import { connection } from '../server'
65
import Indexer from './Indexer'
6+
import ClientConnection from '../ClientConnection'
77

88
/**
99
* Handles indexing files in the user's workspace to gather data about classes,
1010
* functions, and variables.
1111
*/
12-
class WorkspaceIndexer {
12+
export default class WorkspaceIndexer {
1313
private isWorkspaceIndexingSupported = false
1414

15+
constructor (private indexer: Indexer) {}
16+
1517
/**
1618
* Sets up workspace change listeners, if supported.
1719
*
@@ -26,7 +28,7 @@ class WorkspaceIndexer {
2628
return
2729
}
2830

29-
connection.workspace.onDidChangeWorkspaceFolders((params: WorkspaceFoldersChangeEvent) => {
31+
ClientConnection.getConnection().workspace.onDidChangeWorkspaceFolders((params: WorkspaceFoldersChangeEvent) => {
3032
void this.handleWorkspaceFoldersAdded(params.added)
3133
})
3234
}
@@ -39,13 +41,13 @@ class WorkspaceIndexer {
3941
return
4042
}
4143

42-
const folders = await connection.workspace.getWorkspaceFolders()
44+
const folders = await ClientConnection.getConnection().workspace.getWorkspaceFolders()
4345

4446
if (folders == null) {
4547
return
4648
}
4749

48-
void Indexer.indexFolders(folders.map(folder => folder.uri))
50+
void this.indexer.indexFolders(folders.map(folder => folder.uri))
4951
}
5052

5153
/**
@@ -58,7 +60,7 @@ class WorkspaceIndexer {
5860
return
5961
}
6062

61-
void Indexer.indexFolders(folders.map(folder => folder.uri))
63+
void this.indexer.indexFolders(folders.map(folder => folder.uri))
6264
}
6365

6466
/**
@@ -73,5 +75,3 @@ class WorkspaceIndexer {
7375
return this.isWorkspaceIndexingSupported && shouldIndexWorkspace
7476
}
7577
}
76-
77-
export default new WorkspaceIndexer()

0 commit comments

Comments
 (0)