Skip to content

Commit 796c7b2

Browse files
committed
Fixes #348
1 parent 12df49a commit 796c7b2

File tree

3 files changed

+37
-70
lines changed

3 files changed

+37
-70
lines changed

.github/workflows/ci.yml

+8-1
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,20 @@ jobs:
7474
needs: build
7575
if: success() && github.event_name == 'push'
7676
steps:
77-
- name: Download packages and metadata
77+
- name: Download metadata
7878
uses: actions/download-artifact@v4
79+
with:
80+
name: meta
81+
path: .
7982
- name: Set version output
8083
id: set-version
8184
run: |
8285
set -x
8386
echo "version=`cat meta.version`" >> $GITHUB_OUTPUT
87+
- name: Download packages
88+
uses: actions/download-artifact@v4
89+
with:
90+
pattern: '**/*.vsix'
8491
- name: Create Release
8592
id: create-release
8693
uses: softprops/action-gh-release@v2

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## [2.6.2] - 2024-XX-XX
44
- Fix issue [#345](https://github.com/intersystems/language-server/issues/345): Add intellisense for variables passed by reference as method arguments
55
- Fix issue [#347](https://github.com/intersystems/language-server/issues/347): Setting a variable's subscript should not affect the type of that variable
6+
- Fix issue [#348](https://github.com/intersystems/language-server/issues/348): Support intellisense for method arguments that don't have a declared type
67

78
## [2.6.1] - 2024-08-30
89
- Fix issue [#343](https://github.com/intersystems/language-server/issues/343): foldingRange fails on some C-style block comments

server/src/utils/functions.ts

+28-69
Original file line numberDiff line numberDiff line change
@@ -909,30 +909,16 @@ export async function getClassMemberContext(
909909
context: "system"
910910
};
911911
}
912-
else if (dot > 0 && parsed[line][dot-1].l == ld.cos_langindex && parsed[line][dot-1].s == ld.cos_param_attrindex) {
913-
// The token before the dot is a parameter
914-
915-
const paramcon = await determineParameterClass(doc,parsed,line,dot-1,server);
916-
if (paramcon !== undefined) {
917-
result = paramcon;
918-
}
919-
}
920912
else if (dot > 0 && parsed[line][dot-1].l == ld.cos_langindex && (
913+
parsed[line][dot-1].s == ld.cos_param_attrindex ||
921914
parsed[line][dot-1].s == ld.cos_localdec_attrindex ||
922915
parsed[line][dot-1].s == ld.cos_localvar_attrindex ||
923-
parsed[line][dot-1].s == ld.cos_otw_attrindex
916+
parsed[line][dot-1].s == ld.cos_otw_attrindex ||
917+
parsed[line][dot-1].s == ld.cos_localundec_attrindex
924918
)) {
925-
// The token before the dot is a declared local variable, public variable or warning variable
926-
927-
// First check if it's #Dim'd
928-
let varContext = await determineDeclaredLocalVarClass(doc,parsed,line,dot-1,server,allfiles,inheritedpackages);
929-
if (varContext === undefined) {
930-
// If it's not, attempt to determine the class it was set to
931-
varContext = await determineUndeclaredLocalVarClass(doc,parsed,line,dot-1,server,allfiles,inheritedpackages);
932-
}
933-
if (varContext !== undefined) {
934-
result = varContext;
935-
}
919+
// The token before the dot is a parameter, local variable, public variable or warning variable
920+
const varClass = await determineVariableClass(doc,parsed,line,dot-1,server,allfiles,inheritedpackages);
921+
if (varClass) result = { baseclass: varClass, context: "instance" };
936922
}
937923
else if (dot > 0 && parsed[line][dot-1].l == ld.cos_langindex && parsed[line][dot-1].s == ld.cos_sysv_attrindex) {
938924
// The token before the dot is a system variable
@@ -999,14 +985,6 @@ export async function getClassMemberContext(
999985
}
1000986
}
1001987
}
1002-
else if (dot > 0 && parsed[line][dot-1].l == ld.cos_langindex && parsed[line][dot-1].s == ld.cos_localundec_attrindex) {
1003-
// The token before the dot is an undeclared local variable
1004-
1005-
const localundeccon = await determineUndeclaredLocalVarClass(doc,parsed,line,dot-1,server,allfiles,inheritedpackages);
1006-
if (localundeccon !== undefined) {
1007-
result = localundeccon;
1008-
}
1009-
}
1010988
else if (dot > 0 && parsed[line][dot-1].l == ld.cos_langindex && parsed[line][dot-1].s == ld.cos_jsonb_attrindex) {
1011989
// The token before the dot is a JSON bracket
1012990

@@ -1653,7 +1631,8 @@ async function parseSetCommand(
16531631
!inPostconditional && parsed[ln][tkn].l == ld.cos_langindex &&
16541632
(
16551633
parsed[ln][tkn].s == ld.cos_otw_attrindex || parsed[ln][tkn].s == ld.cos_localundec_attrindex ||
1656-
parsed[ln][tkn].s == ld.cos_localdec_attrindex || parsed[ln][tkn].s == ld.cos_localvar_attrindex
1634+
parsed[ln][tkn].s == ld.cos_localdec_attrindex || parsed[ln][tkn].s == ld.cos_localvar_attrindex ||
1635+
parsed[ln][tkn].s == ld.cos_param_attrindex
16571636
) &&
16581637
doc.getText(Range.create(ln,parsed[ln][tkn].p,ln,parsed[ln][tkn].p+parsed[ln][tkn].c)) == selector &&
16591638
// Variable isn't followed by a dot or a subscript
@@ -1992,7 +1971,8 @@ async function determineUndeclaredLocalVarClass(
19921971
if (next && parsed[next[0]][next[1]].l == ld.cos_langindex &&
19931972
(
19941973
parsed[next[0]][next[1]].s == ld.cos_otw_attrindex || parsed[next[0]][next[1]].s == ld.cos_localundec_attrindex ||
1995-
parsed[next[0]][next[1]].s == ld.cos_localdec_attrindex || parsed[next[0]][next[1]].s == ld.cos_localvar_attrindex
1974+
parsed[next[0]][next[1]].s == ld.cos_localdec_attrindex || parsed[next[0]][next[1]].s == ld.cos_localvar_attrindex ||
1975+
parsed[next[0]][next[1]].s == ld.cos_param_attrindex
19961976
) &&
19971977
doc.getText(Range.create(
19981978
next[0],parsed[next[0]][next[1]].p,
@@ -2650,49 +2630,28 @@ export async function getTextForUri(uri: string, server: ServerSpec): Promise<st
26502630
* @param line The line that the variable is in.
26512631
* @param tkn The token of the variable in the line.
26522632
* @param server The server that doc is associated with.
2633+
*
2634+
* The following optional parameters are only provided when called via `onDiagnostics()`:
2635+
* @param allfiles An array of all files in a database.
2636+
* @param inheritedpackages An array containing packages imported by superclasses of this class.
26532637
*/
26542638
export async function determineVariableClass(
2655-
doc: TextDocument, parsed: compressedline[],
2656-
line: number, tkn: number, server: ServerSpec
2639+
doc: TextDocument, parsed: compressedline[], line: number, tkn: number,
2640+
server: ServerSpec, allfiles?: StudioOpenDialogFile[], inheritedpackages?: string[]
26572641
): Promise<string> {
2658-
let varClass = "";
26592642
if (parsed[line][tkn].s == ld.cos_param_attrindex) {
2660-
// This token is a parameter
2661-
2662-
// Determine the class of the parameter
2663-
const paramcon = await determineParameterClass(doc,parsed,line,tkn,server);
2664-
if (paramcon !== undefined) {
2665-
// The parameter has a class
2666-
varClass = paramcon.baseclass;
2667-
}
2668-
} else if (
2669-
parsed[line][tkn].s == ld.cos_localdec_attrindex ||
2670-
parsed[line][tkn].s == ld.cos_localvar_attrindex ||
2671-
parsed[line][tkn].s == ld.cos_otw_attrindex
2672-
) {
2673-
// This token is a declared local variable, public variable, or warning variable
2674-
2675-
// First check if it's #Dim'd
2676-
let varContext = await determineDeclaredLocalVarClass(doc,parsed,line,tkn,server);
2677-
if (varContext === undefined) {
2678-
// If it's not, attempt to determine the class it was set to
2679-
varContext = await determineUndeclaredLocalVarClass(doc,parsed,line,tkn,server);
2680-
}
2681-
if (varContext !== undefined) {
2682-
// The declared local variable has a class
2683-
varClass = varContext.baseclass;
2684-
}
2685-
} else {
2686-
// This token is an undeclared local variable
2687-
2688-
// Determine the class of the undeclared local variable
2689-
const localundeccon = await determineUndeclaredLocalVarClass(doc,parsed,line,tkn,server);
2690-
if (localundeccon !== undefined) {
2691-
// The undeclared local variable has a class
2692-
varClass = localundeccon.baseclass;
2693-
}
2694-
}
2695-
return varClass;
2643+
// Check if the parameter has a declared type in the formal spec
2644+
const paramcon = await determineParameterClass(doc,parsed,line,tkn,server,allfiles,inheritedpackages);
2645+
if (paramcon?.baseclass) return paramcon.baseclass;
2646+
}
2647+
if (parsed[line][tkn].s != ld.cos_localundec_attrindex && parsed[line][tkn].s != ld.cos_param_attrindex) {
2648+
// Check if the variable is #Dim'd or a known percent variable
2649+
const varContext = await determineDeclaredLocalVarClass(doc,parsed,line,tkn,server,allfiles,inheritedpackages);
2650+
if (varContext?.baseclass) return varContext.baseclass;
2651+
}
2652+
// Fall back to inferring the type from a Set or pass by reference
2653+
const localundeccon = await determineUndeclaredLocalVarClass(doc,parsed,line,tkn,server,allfiles,inheritedpackages);
2654+
return localundeccon?.baseclass ?? "";
26962655
}
26972656

26982657
/** Returns `true` if `keyword` is a valid class member type. */

0 commit comments

Comments
 (0)