1
1
import glob from 'glob' ;
2
2
import path from 'path' ;
3
3
import fs from 'fs/promises' ;
4
+ import fss from 'fs' ;
4
5
import Cache from "vscode-rpgle/language/models/cache" ;
5
6
import { IncludeStatement } from "vscode-rpgle/language/parserTypes" ;
6
7
import { infoOut , warningOut } from './cli' ;
7
8
import { DefinitionType , File , Module , CLParser } from 'vscode-clle/language' ;
8
9
import { DisplayFile as dds } from "vscode-displayfile/src/dspf" ;
9
10
import Document from "vscode-db2i/src/language/sql/document" ;
10
- import { StatementType } from 'vscode-db2i/src/language/sql/types' ;
11
+ import { ObjectRef , StatementType } from 'vscode-db2i/src/language/sql/types' ;
11
12
import { rpgExtensions , clExtensions , ddsExtension , sqlExtensions , srvPgmExtensions , cmdExtensions } from './extensions' ;
12
13
import Parser from "vscode-rpgle/language/parser" ;
13
14
import { setupParser } from './parser' ;
@@ -148,6 +149,16 @@ export class Targets {
148
149
extension
149
150
} ;
150
151
152
+ // If this file is an SQL file, we need to look to see if it has a long name as we need to resolve all names here
153
+ if ( sqlExtensions . includes ( extension . toLowerCase ( ) ) ) {
154
+ const ref = this . sqlObjectDataFromPath ( localPath ) ;
155
+ if ( ref ) {
156
+ if ( ref . object . system ) theObject . systemName = ref . object . system . toUpperCase ( ) ;
157
+ if ( ref . object . name ) theObject . longName = ref . object . name ;
158
+ // theObject.type = ref.type;
159
+ }
160
+ }
161
+
151
162
this . storeResolved ( localPath , theObject ) ;
152
163
153
164
return theObject ;
@@ -224,7 +235,7 @@ export class Targets {
224
235
* Resolves a search to an object. Use `systemName` parameter for short and long name.
225
236
*/
226
237
public searchForObject ( lookFor : ILEObject ) {
227
- return this . getResolvedObjects ( ) . find ( o => ( o . systemName === lookFor . systemName || o . systemName === lookFor . longName ) && o . type === lookFor . type ) ;
238
+ return this . getResolvedObjects ( ) . find ( o => ( lookFor . systemName === o . systemName || ( o . longName && lookFor . systemName === o . longName ) ) && o . type === lookFor . type ) ;
228
239
}
229
240
230
241
public searchForAnyObject ( lookFor : { name : string , types : ObjectType [ ] } ) {
@@ -322,6 +333,7 @@ export class Targets {
322
333
}
323
334
324
335
public loadObjectsFromPaths ( paths : string [ ] ) {
336
+ // optimiseFileList(paths); //Ensure we load SQL files first
325
337
paths . forEach ( p => this . resolvePathToObject ( p ) ) ;
326
338
}
327
339
@@ -1202,6 +1214,9 @@ export class Targets {
1202
1214
. forEach ( ( ref : RpgLookup ) => {
1203
1215
if ( ignoredObjects . includes ( ref . lookup ) ) return ;
1204
1216
1217
+ const previouslyScanned = target . deps . some ( ( r => ( ref . lookup === r . systemName || ref . lookup === r . longName ?. toUpperCase ( ) ) && r . type === `FILE` ) ) ;
1218
+ if ( previouslyScanned ) return ;
1219
+
1205
1220
const resolvedObject = this . searchForObject ( { systemName : ref . lookup , type : `FILE` } ) ;
1206
1221
if ( resolvedObject ) target . deps . push ( resolvedObject )
1207
1222
else {
@@ -1221,7 +1236,7 @@ export class Targets {
1221
1236
line : ref . position ? ref . position . line : undefined
1222
1237
} ) )
1223
1238
. forEach ( ( ref : RpgLookup ) => {
1224
- const previouslyScanned = target . deps . some ( ( r => r . systemName === ref . lookup && r . type === `FILE` ) ) ;
1239
+ const previouslyScanned = target . deps . some ( ( r => ( ref . lookup === r . systemName || ref . lookup === r . longName ?. toUpperCase ( ) ) && r . type === `FILE` ) ) ;
1225
1240
if ( previouslyScanned ) return ;
1226
1241
const resolvedObject = this . searchForObject ( { systemName : ref . lookup , type : `FILE` } ) ;
1227
1242
if ( resolvedObject ) target . deps . push ( resolvedObject )
@@ -1585,6 +1600,50 @@ export class Targets {
1585
1600
return currentItem ;
1586
1601
}
1587
1602
1603
+ /**
1604
+ * This is used when loading in all objects.
1605
+ * SQL sources can have two object names: a system name and a long name
1606
+ * Sadly the long name is not typically part of the path name, so we need to
1607
+ * find the name inside of the source code.
1608
+ */
1609
+ sqlObjectDataFromPath ( fullPath : string ) : ObjectRef | undefined {
1610
+ const relativePath = this . getRelative ( fullPath ) ;
1611
+
1612
+ if ( fss . existsSync ( fullPath ) ) {
1613
+ const content = fss . readFileSync ( fullPath , { encoding : `utf-8` } ) ;
1614
+ const document = new Document ( content ) ;
1615
+
1616
+ const groups = document . getStatementGroups ( ) ;
1617
+
1618
+ if ( groups . length === 0 ) {
1619
+ this . logger . fileLog ( relativePath , {
1620
+ message : `No SQL statements found in file.` ,
1621
+ type : `info`
1622
+ } ) ;
1623
+
1624
+ return ;
1625
+ }
1626
+
1627
+ const createCount = groups . filter ( g => g . statements [ 0 ] . type === StatementType . Create ) . length ;
1628
+
1629
+ if ( createCount > 1 ) {
1630
+ this . logger . fileLog ( relativePath , {
1631
+ message : `Includes multiple create statements. They should be in individual sources. This file will not be parsed.` ,
1632
+ type : `warning` ,
1633
+ } ) ;
1634
+ }
1635
+
1636
+ const firstGroup = groups [ 0 ] ;
1637
+ const create = firstGroup . statements . find ( s => s . type === StatementType . Create ) ;
1638
+
1639
+ if ( create ) {
1640
+ const defs = create . getObjectReferences ( ) ;
1641
+ const mainDef = defs . find ( d => d . createType ) ;
1642
+
1643
+ return mainDef ;
1644
+ }
1645
+ }
1646
+ }
1588
1647
}
1589
1648
1590
1649
function trimQuotes ( input : string , value = `'` ) {
0 commit comments