Skip to content

Commit d333ce6

Browse files
committed
Fixes #336
1 parent 414f6db commit d333ce6

File tree

5 files changed

+442
-304
lines changed

5 files changed

+442
-304
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## [2.5.2] - 2024-XX-XX
4+
- Fix issue [#336](https://github.com/intersystems/language-server/issues/336): Add intellisense for variables set to the returned value of a method, or a property, with a declared type
5+
36
## [2.5.1] - 2024-07-09
47
- Fix issue [#328](https://github.com/intersystems/language-server/issues/328): Fix namespace detection for Diagnostic computation
58
- Fix issue [#331](https://github.com/intersystems/language-server/issues/331): Fix display of method arguments with a colon in the default value

server/src/providers/completion.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,9 @@ export async function onCompletion(params: CompletionParams): Promise<Completion
10871087

10881088
// Query the server to get the names and descriptions of all parameters
10891089
const data: QueryData = {
1090-
query: "SELECT Name, Description, Origin, Type, Deprecated FROM %Dictionary.CompiledParameter WHERE parent->ID = ?",
1090+
query: `SELECT Name, Description, Origin, Type, Deprecated FROM %Dictionary.CompiledParameter WHERE parent->ID = ?${
1091+
membercontext.context == "instance" ? " AND (parent->ClassType IS NULL OR parent->ClassType != 'datatype')" : ""
1092+
}`,
10911093
parameters: [membercontext.baseclass]
10921094
}
10931095
const respdata = await makeRESTRequest("POST",1,"/action/query",server,data);
@@ -1156,17 +1158,20 @@ export async function onCompletion(params: CompletionParams): Promise<Completion
11561158
}
11571159
else if (membercontext.context == "instance") {
11581160
data.query = "SELECT Name, Description, Origin, FormalSpec, ReturnType AS Type, 'method' AS MemberType, Deprecated, NULL AS Aliases " +
1159-
"FROM %Dictionary.CompiledMethod WHERE parent->ID = ? AND Stub IS NULL AND ((Origin = parent->ID) OR (Origin != parent->ID AND NotInheritable = 0)) UNION ALL %PARALLEL " +
1161+
"FROM %Dictionary.CompiledMethod WHERE parent->ID = ? AND Stub IS NULL AND ((Origin = parent->ID) OR (Origin != parent->ID AND NotInheritable = 0)) " +
1162+
"AND (parent->ClassType IS NULL OR parent->ClassType != 'datatype') UNION ALL %PARALLEL " +
11601163
"SELECT parent->name||Name AS Name, Description, parent->Origin AS Origin, FormalSpec, ReturnType AS Type, 'method' AS MemberType, Deprecated, NULL AS Aliases " +
1161-
"FROM %Dictionary.CompiledIndexMethod WHERE parent->parent->ID = ? UNION ALL %PARALLEL " +
1164+
"FROM %Dictionary.CompiledIndexMethod WHERE parent->parent->ID = ? AND (parent->parent->ClassType IS NULL OR parent->parent->ClassType != 'datatype') UNION ALL %PARALLEL " +
11621165
"SELECT parent->name||Name AS Name, Description, parent->Origin AS Origin, FormalSpec, ReturnType AS Type, 'method' AS MemberType, Deprecated, NULL AS Aliases " +
1163-
"FROM %Dictionary.CompiledQueryMethod WHERE parent->parent->ID = ? UNION ALL %PARALLEL " +
1166+
"FROM %Dictionary.CompiledQueryMethod WHERE parent->parent->ID = ? AND (parent->parent->ClassType IS NULL OR parent->parent->ClassType != 'datatype') UNION ALL %PARALLEL " +
11641167
"SELECT parent->name||Name AS Name, Description, parent->Origin AS Origin, FormalSpec, ReturnType AS Type, 'method' AS MemberType, Deprecated, NULL AS Aliases " +
1165-
"FROM %Dictionary.CompiledPropertyMethod WHERE parent->parent->ID = ? UNION ALL %PARALLEL " +
1168+
"FROM %Dictionary.CompiledPropertyMethod WHERE parent->parent->ID = ? AND (parent->parent->ClassType IS NULL OR parent->parent->ClassType != 'datatype') UNION ALL %PARALLEL " +
11661169
"SELECT parent->name||Name AS Name, Description, parent->Origin AS Origin, FormalSpec, ReturnType AS Type, 'method' AS MemberType, Deprecated, NULL AS Aliases " +
1167-
"FROM %Dictionary.CompiledConstraintMethod WHERE parent->parent->ID = ? UNION ALL %PARALLEL " +
1168-
"SELECT Name, Description, Origin, NULL AS FormalSpec, RuntimeType AS Type, 'property' AS MemberType, Deprecated, Aliases FROM %Dictionary.CompiledProperty WHERE parent->ID = ? UNION ALL %PARALLEL " +
1169-
"SELECT Name, Description, Origin, NULL AS FormalSpec, Type, 'parameter' AS MemberType, Deprecated, NULL AS Aliases FROM %Dictionary.CompiledParameter WHERE parent->ID = ?";
1170+
"FROM %Dictionary.CompiledConstraintMethod WHERE parent->parent->ID = ? AND (parent->parent->ClassType IS NULL OR parent->parent->ClassType != 'datatype') UNION ALL %PARALLEL " +
1171+
"SELECT Name, Description, Origin, NULL AS FormalSpec, RuntimeType AS Type, 'property' AS MemberType, Deprecated, Aliases " +
1172+
"FROM %Dictionary.CompiledProperty WHERE parent->ID = ? AND (parent->ClassType IS NULL OR parent->ClassType != 'datatype') UNION ALL %PARALLEL " +
1173+
"SELECT Name, Description, Origin, NULL AS FormalSpec, Type, 'parameter' AS MemberType, Deprecated, NULL AS Aliases " +
1174+
"FROM %Dictionary.CompiledParameter WHERE parent->ID = ? AND (parent->ClassType IS NULL OR parent->ClassType != 'datatype')";
11701175
data.parameters = new Array(7).fill(membercontext.baseclass);
11711176
}
11721177
else {

server/src/providers/diagnostic.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ export async function onDiagnostics(params: DocumentDiagnosticParams): Promise<D
775775
else if (parsed[i][j].s == ld.cos_mem_attrindex) {
776776
// This is a generic member
777777

778-
if (membercontext.baseclass.substr(0,7) === "%SYSTEM") {
778+
if (membercontext.baseclass.startsWith("%SYSTEM.")) {
779779
// This is always a method
780780
addRangeToMapVal(methods,memberstr,memberrange);
781781
}

server/src/providers/typeDefinition.ts

+25-82
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { TextDocumentPositionParams, Position, Range } from 'vscode-languageserver';
2-
import { getServerSpec, findFullRange, quoteUDLIdentifier, makeRESTRequest, createDefinitionUri, determineVariableClass, getClassMemberContext, getParsedDocument, getTextForUri } from '../utils/functions';
2+
import { getServerSpec, findFullRange, quoteUDLIdentifier, makeRESTRequest, createDefinitionUri, determineVariableClass, getClassMemberContext, getParsedDocument, getTextForUri, currentClass, getMemberType } from '../utils/functions';
33
import { ServerSpec, QueryData } from '../utils/types';
44
import { documents } from '../utils/variables';
55
import * as ld from '../utils/languageDefinitions';
@@ -27,101 +27,44 @@ export async function onTypeDefinition(params: TextDocumentPositionParams) {
2727
parsed[params.position.line][i].l == ld.cos_langindex && (
2828
parsed[params.position.line][i].s == ld.cos_method_attrindex ||
2929
parsed[params.position.line][i].s == ld.cos_attr_attrindex ||
30-
parsed[params.position.line][i].s == ld.cos_mem_attrindex
30+
parsed[params.position.line][i].s == ld.cos_mem_attrindex ||
31+
parsed[params.position.line][i].s == ld.cos_instvar_attrindex
3132
)
3233
) {
3334
// This token is a method or property
3435

3536
// Get the full text of the member
3637
originrange = findFullRange(params.position.line,parsed,i,symbolstart,symbolend);
37-
let member = quoteUDLIdentifier(doc.getText(originrange),0);
38+
const member = quoteUDLIdentifier(doc.getText(originrange).slice(parsed[params.position.line][i].s == ld.cos_instvar_attrindex ? 2 : 0),0);
3839

39-
// Find the dot token
40-
let dottkn = 0;
41-
for (let tkn = 0; tkn < parsed[params.position.line].length; tkn ++) {
42-
if (parsed[params.position.line][tkn].p >= originrange.start.character) {
43-
break;
40+
let membercontext = {
41+
baseclass: "",
42+
context: ""
43+
};
44+
if (parsed[params.position.line][i].s != ld.cos_instvar_attrindex) {
45+
// Find the dot token
46+
var dottkn = 0;
47+
for (let tkn = 0; tkn < parsed[params.position.line].length; tkn ++) {
48+
if (parsed[params.position.line][tkn].p >= originrange.start.character) {
49+
break;
50+
}
51+
dottkn = tkn;
4452
}
45-
dottkn = tkn;
46-
}
4753

48-
// Get the base class that this member is in
49-
const membercontext = await getClassMemberContext(doc,parsed,dottkn,params.position.line,server);
54+
// Get the base class that this member is in
55+
membercontext = await getClassMemberContext(doc,parsed,dottkn,params.position.line,server);
56+
} else {
57+
membercontext = {
58+
baseclass: currentClass(doc,parsed),
59+
context: ""
60+
};
61+
}
5062
if (membercontext.baseclass === "") {
5163
// If we couldn't determine the class, don't return anything
5264
return null;
5365
}
5466

55-
let data: QueryData = {
56-
query: "",
57-
parameters: []
58-
};
59-
if (parsed[params.position.line][i].s == ld.cos_method_attrindex) {
60-
// This is a method
61-
data.query = "SELECT ReturnType AS Type, Stub FROM %Dictionary.CompiledMethod WHERE parent->ID = ? AND name = ?";
62-
data.parameters = [membercontext.baseclass,member];
63-
}
64-
else if (parsed[params.position.line][i].s == ld.cos_attr_attrindex) {
65-
// This is a property
66-
data.query = "SELECT RuntimeType AS Type, NULL AS Stub FROM %Dictionary.CompiledProperty WHERE parent->ID = ? AND name = ?";
67-
data.parameters = [membercontext.baseclass,member];
68-
}
69-
else {
70-
// This is a generic member
71-
if (membercontext.baseclass.substr(0,7) === "%SYSTEM") {
72-
// This is always a method
73-
data.query = "SELECT ReturnType AS Type, Stub FROM %Dictionary.CompiledMethod WHERE parent->ID = ? AND name = ?";
74-
data.parameters = [membercontext.baseclass,member];
75-
}
76-
else {
77-
// This can be a method or property
78-
data.query = "SELECT ReturnType AS Type, Stub FROM %Dictionary.CompiledMethod WHERE parent->ID = ? AND name = ? UNION ALL ";
79-
data.query = data.query.concat("SELECT RuntimeType AS Type, NULL AS Stub FROM %Dictionary.CompiledProperty WHERE parent->ID = ? AND name = ?");
80-
data.parameters = [membercontext.baseclass,member,membercontext.baseclass,member];
81-
}
82-
}
83-
const respdata = await makeRESTRequest("POST",1,"/action/query",server,data);
84-
if (Array.isArray(respdata?.data?.result?.content) && respdata.data.result.content.length > 0) {
85-
// We got data back
86-
87-
let memobj = respdata.data.result.content[0];
88-
if (respdata.data.result.content[0].Stub !== "") {
89-
// This is a method generated by member inheritance, so we need to get its type from the proper subtable
90-
91-
const stubarr = respdata.data.result.content[0].Stub.split(".");
92-
let stubquery = "";
93-
if (stubarr[2] === "i") {
94-
// This is a method generated from an index
95-
stubquery = "SELECT ReturnType AS Type FROM %Dictionary.CompiledIndexMethod WHERE Name = ? AND parent->parent->ID = ? AND parent->Name = ?";
96-
}
97-
if (stubarr[2] === "q") {
98-
// This is a method generated from a query
99-
stubquery = "SELECT ReturnType AS Type FROM %Dictionary.CompiledQueryMethod WHERE Name = ? AND parent->parent->ID = ? AND parent->Name = ?";
100-
}
101-
if (stubarr[2] === "a") {
102-
// This is a method generated from a property
103-
stubquery = "SELECT ReturnType AS Type FROM %Dictionary.CompiledPropertyMethod WHERE Name = ? AND parent->parent->ID = ? AND parent->Name = ?";
104-
}
105-
if (stubarr[2] === "n") {
106-
// This is a method generated from a constraint
107-
stubquery = "SELECT ReturnType AS Type FROM %Dictionary.CompiledConstraintMethod WHERE Name = ? AND parent->parent->ID = ? AND parent->Name = ?";
108-
}
109-
if (stubquery !== "") {
110-
const stubrespdata = await makeRESTRequest("POST",1,"/action/query",server,{
111-
query: stubquery,
112-
parameters: [stubarr[1],membercontext.baseclass,stubarr[0]]
113-
});
114-
if (Array.isArray(stubrespdata?.data?.result?.content) && stubrespdata.data.result.content.length > 0) {
115-
// We got data back
116-
memobj = stubrespdata.data.result.content[0];
117-
}
118-
}
119-
}
120-
121-
if (memobj.Type !== "") {
122-
targetcls = memobj.Type;
123-
}
124-
}
67+
targetcls = await getMemberType(parsed,params.position.line,i,membercontext.baseclass,member,server);
12568
}
12669
else {
12770
// This token is an ObjectScript variable

0 commit comments

Comments
 (0)