Skip to content

Commit 0bebb79

Browse files
authored
Merge pull request #63 from mathworks/dklilley/release/1.3.4
MATLAB language server - v1.3.4
2 parents 4886ff0 + 1bcffc6 commit 0bebb79

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+10137
-33710
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
],
1313
"internalConsoleOptions": "openOnSessionStart",
1414
"name": "Mocha Tests",
15-
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
15+
"program": "${workspaceFolder}/node_modules/mocha/bin/mocha",
1616
"request": "launch",
1717
"skipFiles": [
1818
"<node_internals>/**"

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ MATLAB language server implements several Language Server Protocol features and
1010
* Code diagnostics — [publishDiagnostics](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_publishDiagnostics)
1111
* Quick fixes — [codeActionProvider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction)
1212
* Document formatting — [documentFormattingProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting)
13+
* Document range formatting - [documentRangeFormattingProvider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rangeFormatting)
1314
* Code completions — [completionProvider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion)
1415
* Function signature help — [signatureHelpProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp)
1516
* Go to definition — [definitionProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition)
1617
* Go to references — [referencesProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references)
17-
* Document symbols — [documentSymbol](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol)
18+
* Document symbols — [documentSymbolProvider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol)
1819
* Symbol rename - [renameProvider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename)
20+
* Code folding - [foldingRangeProvider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange)
1921

2022
## Clients
2123
MATLAB language server supports these editors by installing the corresponding extension:
@@ -26,6 +28,18 @@ MATLAB language server supports these editors by installing the corresponding ex
2628

2729
### Unreleased
2830

31+
### 1.3.4
32+
Release date: 2025-07-31
33+
34+
Added:
35+
* Support for document range formatting
36+
* Document symbol model now include methods, properties, and enumerations for improved navigation
37+
38+
Fixed:
39+
* Resolves a crash that occurs when language server is used over stdin/stdout
40+
* Resolves issue where language server stops working after calling `restoredefaultpath`
41+
* Applied patches for CVE-2023-44270, CVE-2024-11831, CVE-2025-27789, CVE-2025-30359, CVE-2025-30360, CVE-2025-32996, and CVE-2025-5889
42+
2943
### 1.3.3
3044
Release date: 2025-05-15
3145

matlab/+matlabls/+handlers/+formatting/formatCode.m

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,103 @@
1-
function formattedCode = formatCode (codeToFormat, options)
2-
% FORMATCODE Formats the given MATLAB code according to the specified options.
1+
function formattedCode = formatCode (code, startLine, endLine, options)
2+
% FORMATCODE Formats the specifid line range of the given MATLAB
3+
% code according to the provided options.
4+
%
5+
% Note: `startLine` and `endLine` should be provided as 0-based line numbers.
36

47
% Copyright 2025 The MathWorks, Inc.
58

6-
s = settings;
7-
89
% Update settings (temporarily) for formatting
10+
s = settings;
911
cleanupObj1 = setTemporaryValue(s.matlab.editor.tab.InsertSpaces, options.insertSpaces); %#ok<NASGU>
1012
cleanupObj2 = setTemporaryValue(s.matlab.editor.tab.TabSize, options.tabSize); %#ok<NASGU>
1113
cleanupObj3 = setTemporaryValue(s.matlab.editor.tab.IndentSize, options.tabSize); %#ok<NASGU>
1214

13-
% Format code
14-
formattedCode = indentcode(codeToFormat);
15+
% Formatting logic expects 1-based line numbers
16+
formattedCode = doFormatLines(code, startLine + 1, endLine + 1, options);
17+
end
18+
19+
function formattedCode = doFormatLines (code, startLine, endLine, options)
20+
% Standardize line endings to \n
21+
code = regexprep(code , sprintf('(\r\n)|\r|\n'), newline);
22+
23+
lines = strsplit(code, newline, CollapseDelimiters = false);
24+
25+
% Determine the range of lines to format
26+
if startLine == 1
27+
% Case 1: start is the first code line
28+
linesToFormat = lines(startLine:endLine);
29+
else
30+
% Case 2: start is not the first code line
31+
% In this case, we include the preceding line when formatting to
32+
% ensure the indentation of startLine is correct with respect to
33+
% the previous line.
34+
linesToFormat = lines(startLine-1:endLine);
35+
end
36+
37+
% Format the lines using the indentcode function
38+
formattedCode = indentcode(strjoin(linesToFormat, '\n'));
39+
formattedLines = strsplit(formattedCode, '\n', CollapseDelimiters = false);
40+
41+
% Replace the respective lines in the original snippet
42+
if startLine == 1
43+
lines(startLine:endLine) = formattedLines;
44+
else
45+
% Calculate the difference in indentation
46+
originalIndent = regexp(lines{startLine-1}, '^\s*', 'match', 'once');
47+
newIndent = regexp(formattedLines{1}, '^\s*', 'match', 'once');
48+
diff = getWhitespaceLength(originalIndent, options.tabSize) - getWhitespaceLength(newIndent, options.tabSize);
49+
50+
if diff ~= 0
51+
% Adjust whitespace indent of formatted lines [startLine:endLine]
52+
for i = 2:numel(formattedLines)
53+
if options.insertSpaces
54+
formattedLines{i} = append(getWhitespaceStringOfLength(diff, true, options.tabSize), formattedLines{i});
55+
else
56+
existingWhitespace = regexp(formattedLines{i}, '^\s*', 'match', 'once');
57+
existingWhitespaceLength = getWhitespaceLength(existingWhitespace, options.tabSize);
58+
targetWhitespaceLength = existingWhitespaceLength + diff;
59+
60+
newWhitespace = getWhitespaceStringOfLength(targetWhitespaceLength, false, options.tabSize);
61+
formattedLines{i} = append(newWhitespace, strip(formattedLines{i}, 'left'));
62+
end
63+
end
64+
end
65+
66+
% Replace the formatted lines
67+
lines(startLine:endLine) = formattedLines(2:end);
68+
end
69+
70+
% Join the lines back into a single string
71+
formattedCode = strjoin(lines, '\n');
72+
end
73+
74+
function lengthInSpaces = getWhitespaceLength (whitespaceStr, tabSize)
75+
lengthInSpaces = 0;
76+
77+
% Iterate through each character in the string
78+
for i = 1:length(whitespaceStr)
79+
charAtPos = whitespaceStr(i);
80+
81+
if charAtPos == ' '
82+
% Space character - add length of 1
83+
lengthInSpaces = lengthInSpaces + 1;
84+
else
85+
% Assume tab character
86+
% The length will now be the next multiple of `tabSize`
87+
lengthInSpaces = floor(lengthInSpaces / tabSize + 1) * tabSize;
88+
end
89+
end
90+
end
91+
92+
function whitespaceStr = getWhitespaceStringOfLength (length, insertSpaces, tabSize)
93+
if insertSpaces
94+
whitespaceStr = blanks(length);
95+
else
96+
% Calculate how many tab characters and additional spaces are needed
97+
nTabs = floor(length / tabSize);
98+
nSpaces = rem(length, tabSize);
99+
whitespaceStr = append(repmat(char(9), 1, nTabs), blanks(nSpaces));
100+
end
15101
end
16102

17103
function cleanupObj = setTemporaryValue (setting, tempValue)
205 Bytes
Binary file not shown.

matlab/initmatlabls.m

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,8 @@ function initmatlabls (outFile)
1212

1313
% Ensure the language server code is on the path
1414
folder = fileparts(mfilename('fullpath'));
15-
addpath(folder)
1615

17-
try
18-
if isMATLABReleaseOlderThan('R2023a')
19-
addpath(fullfile(folder, 'shadows', 'clc'));
20-
end
21-
catch ME
22-
disp('Error while attempting to add shadow directory to path')
23-
disp(ME.message)
24-
end
16+
updatePath(folder);
2517

2618
try
2719
s = settings;
@@ -75,4 +67,30 @@ function logConnectionData (outFile)
7567
if ~status
7668
error('Failed to rename connection file.')
7769
end
70+
71+
end
72+
73+
function updatePath(languageServerFolder)
74+
addpath(languageServerFolder)
75+
76+
try
77+
addRestoreDefaultPathShadow(languageServerFolder);
78+
79+
if isMATLABReleaseOlderThan('R2023a')
80+
addpath(fullfile(languageServerFolder, 'shadows', 'clc'));
81+
end
82+
catch ME
83+
disp('Error while attempting to add shadow directory to path')
84+
disp(ME.message)
85+
end
86+
end
87+
88+
function addRestoreDefaultPathShadow(languageServerFolder)
89+
currentDirectory = pwd;
90+
cd(fullfile(matlabroot, 'toolbox', 'local'));
91+
originalRestoreDefaultPath = @restoredefaultpath;
92+
cd(matlabroot);
93+
addpath(fullfile(languageServerFolder, 'shadows', 'restoredefaultpath'));
94+
restoredefaultpath('SET', originalRestoreDefaultPath, @() updatePath(languageServerFolder));
95+
cd(currentDirectory);
7896
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function restoredefaultpath(varargin)
2+
mlock
3+
persistent originalRestoreDefaultPath;
4+
persistent pathUpdateFunction;
5+
if nargin == 3 && ischar(varargin{1}) && isequal(varargin{1}, 'SET')
6+
originalRestoreDefaultPath = varargin{2};
7+
pathUpdateFunction = varargin{3};
8+
return;
9+
end
10+
11+
if isempty(originalRestoreDefaultPath)
12+
error('Matlab Language Server - RestoreDefaultPath shadow is uninitialized.');
13+
end
14+
15+
originalRestoreDefaultPath();
16+
pathUpdateFunction();
17+
end

0 commit comments

Comments
 (0)