Skip to content

Commit

Permalink
Merge pull request mathworks#16 from development/dlilley.Feature_Navi…
Browse files Browse the repository at this point in the history
…gation

Feature: Navigation support
  • Loading branch information
dklilley authored and GitHub Enterprise committed Dec 13, 2022
2 parents 2d285e3 + 5c3bc58 commit 45a65ed
Show file tree
Hide file tree
Showing 5 changed files with 664 additions and 15 deletions.
19 changes: 10 additions & 9 deletions matlab/+matlabls/+internal/computeCodeData.m
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
topLevelFunctionNode = topLevelFunctionNode.trueparent;
end
[declLineEnd, declCharEnd] = topLevelFunctionNode.pos2lc(topLevelFunctionNode.righttreepos);
functionInfo.declaration = createRange(functionInfo.range.lineStart, functionInfo.range.charStart, declLineEnd, declCharEnd);
functionInfo.declaration = createRange(functionInfo.range.lineStart, functionInfo.range.charStart, declLineEnd, declCharEnd + 1);
end

if ~isClassDef
Expand Down Expand Up @@ -391,14 +391,15 @@
end

function variableInfo = addVariableInfoImpl (vars, ranges, variableInfo, field)
info = cell(1, numel(vars));
for k = 1:numel(vars)
name = vars{k};
if isempty(name)
info{k} = {};
continue
end
info{k} = { name, ranges(k) };
% Remove any empty entries - these could be caused by function input
% arguments being omitted using ~
nonemptyIndices = ~cellfun(@isempty, vars);
validVars = vars(nonemptyIndices);
validRanges = ranges(nonemptyIndices);

info = cell(1, numel(validVars));
for k = 1:numel(validVars)
info{k} = { validVars{k}, validRanges(k) };
end
if ~isfield(variableInfo, field)
variableInfo.(field) = info;
Expand Down
42 changes: 36 additions & 6 deletions src/indexing/FileInfoIndex.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Range } from 'vscode-languageserver'
import { Position, Range } from 'vscode-languageserver'
import { isPositionGreaterThan, isPositionLessThanOrEqualTo } from '../utils/PositionUtils'

/**
* Defines the structure of the raw data retrieved from MATLAB.
Expand Down Expand Up @@ -33,7 +34,7 @@ interface CodeDataFunctionInfo {
range: CodeDataRange
parentClass: string
isPublic: boolean
declaration: CodeDataRange
declaration?: CodeDataRange // Will be undefined if function is prototype
variableInfo: CodeDataFunctionVariableInfo
globals: string[]
isPrototype: boolean
Expand Down Expand Up @@ -219,7 +220,7 @@ export class MatlabClassInfo {
/**
* Class to contain info about members of a class (e.g. Properties or Enumerations)
*/
class MatlabClassMemberInfo {
export class MatlabClassMemberInfo {
readonly name: string
readonly range: Range
readonly parentClass: string
Expand All @@ -234,11 +235,11 @@ class MatlabClassMemberInfo {
/**
* Class to contain info about functions
*/
class MatlabFunctionInfo {
export class MatlabFunctionInfo {
name: string

range: Range
declaration: Range
declaration: Range | null

isPrototype: boolean

Expand All @@ -252,7 +253,7 @@ class MatlabFunctionInfo {
this.name = rawFunctionInfo.name

this.range = convertRange(rawFunctionInfo.range)
this.declaration = convertRange(rawFunctionInfo.declaration)
this.declaration = rawFunctionInfo.declaration != null ? convertRange(rawFunctionInfo.declaration) : null

this.isPrototype = rawFunctionInfo.isPrototype

Expand Down Expand Up @@ -363,6 +364,35 @@ export class MatlabCodeData {
return this.classInfo != null
}

/**
* Finds the info for the function containing the given position.
*
* @param position A position in the document
* @returns The info for the function containing the position, or null if no function contains that position.
*/
findContainingFunction (position: Position): MatlabFunctionInfo | null {
let containingFunction: MatlabFunctionInfo | null = null

for (const functionInfo of this.functions.values()) {
const start = functionInfo.range.start
const end = functionInfo.range.end

// Check if position is within range
if (isPositionLessThanOrEqualTo(start, position) && isPositionGreaterThan(end, position)) {
if (containingFunction == null) {
containingFunction = functionInfo
} else {
// Prefer a narrower function if we already have a match (e.g. nested functions)
if (isPositionGreaterThan(start, containingFunction.range.start)) {
containingFunction = functionInfo
}
}
}
}

return containingFunction
}

/**
* Parses information about the file's functions.
*
Expand Down
Loading

0 comments on commit 45a65ed

Please sign in to comment.