Skip to content

Commit 23dd88f

Browse files
authored
Merge pull request #129 from IBM/cleanup/remove_use_of_glob_for_cache
Remove use of glob for cache
2 parents 5218b51 + a0b31a5 commit 23dd88f

File tree

5 files changed

+158
-31
lines changed

5 files changed

+158
-31
lines changed

cli/package-lock.json

Lines changed: 80 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/src/languages/rpgle.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function setupParser(targets: Targets): Parser {
2626
// Keep making the path less specific until we find a possible include
2727
let parts = includeFile.split(`/`);
2828
while (!file && parts.length > 0) {
29-
file = targets.resolveLocalFile(includeFile);
29+
file = await targets.resolveLocalFile(includeFile);
3030

3131
if (!file) {
3232
parts.shift();
@@ -39,9 +39,9 @@ export function setupParser(targets: Targets): Parser {
3939
includeFile = `${parent}/${includeFile}`;
4040

4141

42-
file = targets.resolveLocalFile(includeFile);
42+
file = await targets.resolveLocalFile(includeFile);
4343
} else {
44-
file = targets.resolveLocalFile(includeFile);
44+
file = await targets.resolveLocalFile(includeFile);
4545
}
4646

4747
if (file) {

cli/src/targets.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import glob from 'glob';
21
import path from 'path';
32
import Cache from "vscode-rpgle/language/models/cache";
43
import { IncludeStatement } from "vscode-rpgle/language/parserTypes";
@@ -11,7 +10,7 @@ import { rpgExtensions, clExtensions, ddsExtension, sqlExtensions, srvPgmExtensi
1110
import Parser from "vscode-rpgle/language/parser";
1211
import { setupParser } from './languages/rpgle';
1312
import { Logger } from './logger';
14-
import { asPosix, getReferenceObjectsFrom, getSystemNameFromPath, toLocalPath } from './utils';
13+
import { asPosix, getReferenceObjectsFrom, getSystemNameFromPath, globalEntryIsValid, toLocalPath } from './utils';
1514
import { extCanBeProgram, getObjectType } from './builders/environment';
1615
import { isSqlFunction } from './languages/sql';
1716
import { ReadFileSystem } from './readFileSystem';
@@ -294,40 +293,43 @@ export class Targets {
294293
return this.getResolvedObjects().find(o => (o.systemName === lookFor.name || o.longName?.toUpperCase() === lookFor.name) && (lookFor.types === undefined || lookFor.types.includes(o.type)));
295294
}
296295

297-
public resolveLocalFile(name: string, baseFile?: string): string | undefined {
296+
public async resolveLocalFile(name: string, baseFile?: string): Promise<string> {
298297
name = name.toUpperCase();
299298

300299
if (this.resolvedSearches[name]) return this.resolvedSearches[name];
301300

302301
if (!this.pathCache) {
303-
// We don't really want to spam the FS
304-
// So we can a list of files which can then
305-
// use in glob again later.
306302
this.pathCache = {};
307303

308-
glob.sync(`**/*`, {
304+
(await this.fs.getFiles(this.getCwd(), `**/*`, {
309305
cwd: this.cwd,
310306
absolute: true,
311307
nocase: true,
312-
}).forEach(localPath => {
308+
})).forEach(localPath => {
313309
this.pathCache[localPath] = true;
314310
});
315311
}
316312

317-
let globString = `**/${name}*`;
313+
const searchCache = (): string|undefined => {
314+
for (let entry in this.pathCache) {
315+
if (Array.isArray(this.pathCache[entry])) {
316+
const subEntry = this.pathCache[entry].find(e => globalEntryIsValid(e, name));
317+
if (subEntry) {
318+
return subEntry;
319+
}
320+
} else {
321+
if (globalEntryIsValid(entry, name)) {
322+
return entry;
323+
}
324+
}
325+
}
326+
}
318327

319-
// TODO: replace with rfs.getFiles
320-
const results = glob.sync(globString, {
321-
cwd: this.cwd,
322-
absolute: true,
323-
nocase: true,
324-
ignore: baseFile ? `**/${baseFile}` : undefined,
325-
cache: this.pathCache
326-
});
328+
const result = searchCache();
327329

328-
if (results[0]) {
330+
if (result) {
329331
// To local path is required because glob returns posix paths
330-
const localPath = toLocalPath(results[0])
332+
const localPath = toLocalPath(result)
331333
this.resolvedSearches[name] = localPath;
332334
return localPath;
333335
}

cli/src/utils.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,56 @@ export function checkFileExists(file) {
262262
return fs.promises.access(file, fs.constants.F_OK)
263263
.then(() => true)
264264
.catch(() => false)
265+
}
266+
267+
export function globalEntryIsValid(fullPath: string, search: string, ignoreBase?: string) {
268+
search = search.toUpperCase();
269+
270+
if (ignoreBase) {
271+
if (fullPath.toUpperCase().endsWith(ignoreBase.toUpperCase())) {
272+
return false;
273+
}
274+
}
275+
276+
const baseParts = fullPath.toUpperCase().split(path.sep);
277+
const nameParts = search.split(path.sep);
278+
279+
// Check the preceding parts of the path match
280+
if (nameParts.length > 1) {
281+
for (let i = 1; i < nameParts.length - 1; i++) {
282+
const bPart = baseParts[baseParts.length - i];
283+
const nPart = nameParts[nameParts.length - i - 1];
284+
285+
if (bPart && nPart) {
286+
if (bPart !== nPart) return false;
287+
}
288+
}
289+
}
290+
291+
const baseName = nameParts[nameParts.length - 1];
292+
293+
// Check different variations of the name.
294+
295+
if (baseName.endsWith('*')) {
296+
// If the name ends with *, we do a startsWith check
297+
const tempName = search.substring(0, search.length - 1);
298+
const lastChar = tempName.charAt(tempName.length - 1);
299+
const messedUpFullName = fullPath.lastIndexOf(lastChar) >= 0 ? fullPath.substring(0, fullPath.lastIndexOf(lastChar) + 1) : fullPath;
300+
if (messedUpFullName.toUpperCase().endsWith(tempName)) return true;
301+
} else if (!baseName.includes('.')) {
302+
// If the name does not include a dot, we check if the current part (without extension) matches
303+
let currentPart = baseParts[baseParts.length - 1];
304+
if (currentPart.includes('.')) {
305+
currentPart = currentPart.substring(0, currentPart.indexOf('.'));
306+
}
307+
308+
if (currentPart === baseName) {
309+
return true;
310+
}
311+
312+
} else if (baseParts[baseParts.length - 1] === baseName) {
313+
return true;
314+
}
315+
316+
return false;
265317
}

cli/test/autofix.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ test(`Fix includes in same directory`, async () => {
168168
const programs = targets.getTargetsOfType(`PGM`);
169169
expect(programs.length).toBe(1);
170170

171+
expect(programs[0].headers.length).toBe(1);
172+
171173
let allLogs = targets.logger.getAllLogs();
172174
expect(Object.keys(allLogs).length).toBe(1)
173175

0 commit comments

Comments
 (0)