@@ -7,10 +7,11 @@ import * as ileExports from './apis';
7
7
import skipRules from './linter/skipRules' ;
8
8
import * as Project from "./project" ;
9
9
import { getInterfaces } from './project/exportInterfaces' ;
10
+ import Parser from '../../../../language/parser' ;
10
11
11
12
const completionKind = {
12
- function : CompletionItemKind . Function ,
13
- struct : CompletionItemKind . Struct
13
+ function : CompletionItemKind . Function ,
14
+ struct : CompletionItemKind . Struct
14
15
} ;
15
16
16
17
const eol = `\n` ;
@@ -29,10 +30,10 @@ export default async function completionItemProvider(handler: CompletionParams):
29
30
const isFree = ( document . getText ( Range . create ( 0 , 0 , 0 , 6 ) ) . toUpperCase ( ) === `**FREE` ) ;
30
31
31
32
// If they're typing inside of a procedure, let's get the stuff from there too
32
- const currentProcedure = doc . procedures . find ( ( proc , index ) =>
33
+ const currentProcedure = doc . procedures . find ( ( proc , index ) =>
33
34
proc . range . start && proc . range . end &&
34
- lineNumber >= proc . range . start &&
35
- ( lineNumber <= proc . range . end + 1 || index === doc . procedures . length - 1 ) &&
35
+ lineNumber >= proc . range . start &&
36
+ ( lineNumber <= proc . range . end + 1 || index === doc . procedures . length - 1 ) &&
36
37
currentPath === proc . position . path
37
38
) ;
38
39
@@ -45,42 +46,61 @@ export default async function completionItemProvider(handler: CompletionParams):
45
46
46
47
// This means we're just looking for subfields in the struct
47
48
if ( trigger === `.` ) {
48
- let currentPosition = Position . create ( handler . position . line , handler . position . character - 2 ) ;
49
- let preWord = getWordRangeAtPosition ( document , currentPosition ) ;
49
+ const tokens = Parser . lineTokens ( isFree ? currentLine : currentLine . length >= 7 ? currentLine . substring ( 7 ) : `` , 0 , 0 , true ) ;
50
50
51
- // Uh oh! Maybe we found dim struct?
52
- if ( preWord && preWord . includes ( `)` ) ) {
53
- const startBracket = currentLine . lastIndexOf ( `(` , currentPosition . character ) ;
51
+ if ( tokens . length > 0 ) {
52
+ const cursorIndex = handler . position . character ;
53
+ let tokenIndex = tokens . findIndex ( token => cursorIndex > token . range . start && cursorIndex <= token . range . end ) ;
54
+ console . log ( tokens ) ;
55
+ console . log ( { cPos : handler . position . character , tokenIndex } ) ;
54
56
55
- if ( startBracket > - 1 ) {
56
- currentPosition = Position . create ( handler . position . line , startBracket - 1 ) ;
57
- preWord = getWordRangeAtPosition ( document , currentPosition ) ;
57
+ while ( tokens [ tokenIndex ] && [ `block` , `word` , `dot` ] . includes ( tokens [ tokenIndex ] . type ) && tokenIndex > 0 ) {
58
+ tokenIndex -- ;
58
59
}
59
- }
60
60
61
- // Ok, we have a 'preWord' (the name of the struct?)
62
- if ( preWord ) {
63
- preWord = preWord . toUpperCase ( ) ;
64
-
65
- // Look at the parms or existing structs to find a possible reference
66
- const possibleStruct : Declaration | undefined = [
67
- // First we search the local procedure
68
- currentProcedure && currentProcedure . scope ? currentProcedure . scope . parameters . find ( parm => parm . name . toUpperCase ( ) === preWord && parm . subItems . length > 0 ) : undefined ,
69
- currentProcedure && currentProcedure . scope ? currentProcedure . scope . structs . find ( struct => struct . name . toUpperCase ( ) === preWord ) : undefined ,
70
- currentProcedure && currentProcedure . scope ? currentProcedure . scope . constants . find ( struct => struct . subItems . length > 0 && struct . name . toUpperCase ( ) === preWord ) : undefined ,
71
-
72
- // Then we search the globals
73
- doc . structs . find ( struct => struct . name . toUpperCase ( ) === preWord ) ,
74
- doc . constants . find ( struct => struct . subItems . length > 0 && struct . name . toUpperCase ( ) === preWord )
75
- ] . find ( x => x ) ; // find the first non-undefined item
76
-
77
- if ( possibleStruct && possibleStruct . keyword [ `QUALIFIED` ] ) {
78
- items . push ( ...possibleStruct . subItems . map ( subItem => {
61
+ let currentDef : Declaration | undefined ;
62
+
63
+ for ( tokenIndex ; tokenIndex < tokens . length ; tokenIndex ++ ) {
64
+ if ( [ `block` , `dot` , `newline` ] . includes ( tokens [ tokenIndex ] . type ) ) {
65
+ continue ;
66
+ }
67
+
68
+ const word = tokens [ tokenIndex ] . value ?. toUpperCase ( ) ;
69
+
70
+ if ( ! word ) break ;
71
+
72
+ if ( currentDef ) {
73
+ if ( currentDef . subItems && currentDef . subItems . length > 0 ) {
74
+ currentDef = currentDef . subItems . find ( subItem => subItem . name . toUpperCase ( ) === word ) ;
75
+ }
76
+
77
+ } else {
78
+ currentDef = [
79
+ // First we search the local procedure
80
+ currentProcedure && currentProcedure . scope ? currentProcedure . scope . parameters . find ( parm => parm . name . toUpperCase ( ) === word && parm . subItems . length > 0 ) : undefined ,
81
+ currentProcedure && currentProcedure . scope ? currentProcedure . scope . structs . find ( struct => struct . name . toUpperCase ( ) === word && struct . keyword [ `QUALIFIED` ] ) : undefined ,
82
+ currentProcedure && currentProcedure . scope ? currentProcedure . scope . constants . find ( struct => struct . subItems . length > 0 && struct . name . toUpperCase ( ) === word ) : undefined ,
83
+
84
+ // Then we search the globals
85
+ doc . structs . find ( struct => struct . name . toUpperCase ( ) === word && struct . keyword [ `QUALIFIED` ] ) ,
86
+ doc . constants . find ( constants => constants . subItems . length > 0 && constants . name . toUpperCase ( ) === word )
87
+ ] . find ( x => x ) ; // find the first non-undefined item
88
+
89
+ if ( currentDef && currentDef . subItems . length > 0 ) {
90
+ // All good!
91
+ } else {
92
+ currentDef = undefined ;
93
+ }
94
+ }
95
+ }
96
+
97
+ if ( currentDef && currentDef . subItems . length > 0 ) {
98
+ items . push ( ...currentDef . subItems . map ( subItem => {
79
99
const item = CompletionItem . create ( subItem . name ) ;
80
100
item . kind = CompletionItemKind . Property ;
81
101
item . insertText = subItem . name ;
82
102
item . detail = prettyKeywords ( subItem . keyword ) ;
83
- item . documentation = subItem . description + `${ possibleStruct ? ` (${ possibleStruct . name } )` : `` } ` ;
103
+ item . documentation = subItem . description + ` (${ currentDef . name } )` ;
84
104
return item ;
85
105
} ) ) ;
86
106
}
@@ -100,10 +120,10 @@ export default async function completionItemProvider(handler: CompletionParams):
100
120
item . detail = file . relative ;
101
121
return item ;
102
122
} ) ) ;
103
-
123
+
104
124
} else if ( currentLine . trimStart ( ) . startsWith ( `//` ) ) {
105
125
items . push ( ...skipRules ) ;
106
-
126
+
107
127
} else {
108
128
const expandScope = ( localCache : Cache ) => {
109
129
for ( const subItem of localCache . parameters ) {
@@ -266,7 +286,7 @@ export default async function completionItemProvider(handler: CompletionParams):
266
286
kind : `markdown` ,
267
287
value : [
268
288
currentExport . description ,
269
- ( currentExport . example ?
289
+ ( currentExport . example ?
270
290
[ `---` , '' , '```rpgle' , currentExport . example . join ( eol ) , '```' ] . join ( eol )
271
291
: undefined )
272
292
] . filter ( v => v ) . join ( eol + eol )
0 commit comments