Skip to content

Commit

Permalink
Respect exclude without requiring restart (#545)
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-wiemer authored Oct 17, 2024
1 parent bca5ff7 commit dd40e6f
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 89 deletions.
2 changes: 1 addition & 1 deletion ahk2
Submodule ahk2 updated from f75b53 to d5a3f8
4 changes: 3 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
## 6.3.0 - unreleased 🕳️

- Add exclude setting ([#488](https://github.com/mark-wiemer-org/ahkpp/issues/488))
- Excluded files are not included in IntelliSense completion suggestions, even when they're added via `#include`
- Changed `v2.exclude` setting to `exclude`
- One setting works for both v1 and v2
- Changes to this setting take effect immediately, no need to restart your IDE (different than thqby's extension)
- v2 will exclude excluded files from suggestions even if they're opened in the IDE (different than thqby's extension)
- v1 no longer automatically ignores files with `out`, `target`, and `node_modules` in their name
- v1 no longer automatically ignores files with `out`, `target`, or `node_modules` in their name
- Fixup output channel names: "AHK++ (v1)" and "AHK++ (v2)" instead of "AHK" and "AHK++" respectively
- Fix duplicate output channels

Expand Down
5 changes: 5 additions & 0 deletions e2e/main.ahk1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#NoEnv
#SingleInstance, Force
SendMode, Input
SetBatchLines, -1
SetWorkingDir, %A_ScriptDir%
2 changes: 1 addition & 1 deletion e2e/main.ahk → e2e/main.ahk2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#Requires AutoHotkey v2.0

; Exclude pattern: excluded.ahk
;* Should not suggest "my excluded func" in completion
;* Should not suggest "MyExcludedFunc" in completion
MyExclu
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
],
"scripts": {
"prebuild": "npm run clean:dist",
"build": "node src/build.mjs --mode=production && cd ahk2 && npm run build",
"build:ahk1": "node src/build.mjs --mode=production",
"build:dev": "node src/build.mjs && cd ahk2 && npm run build",
"build": "npm run compile:grammar && node src/build.mjs --mode=production && cd ahk2 && npm run build",
"build:ahk1": "npm run compile:grammar && node src/build.mjs --mode=production",
"build:dev": "npm run compile:grammar && node src/build.mjs && cd ahk2 && npm run build",
"clean": "npm run clean:dist && npm run clean:language && npm run clean:out",
"clean:dist": "del-cli dist",
"clean:language": "del-cli \"language/*.tmLanguage.json\"",
Expand All @@ -72,7 +72,7 @@
"sort-package-json:fix": "sort-package-json",
"test": "npm run test:grammar && npm run test:unit && npm run test:e2e",
"test:ci": "npm run test:grammar && npm run test:e2e:ci",
"pretest:e2e": "npm run vscode:prepublish && npm run compile:ts",
"pretest:e2e": "npm run build && npm run compile:ts",
"test:e2e": "vscode-test",
"test:e2e:ci": "npm run test:e2e -- -i --fgrep @ignoreCI",
"pretest:grammar": "npm run compile:grammar",
Expand All @@ -83,7 +83,7 @@
"validate:ci": "npm run lint && npm run test:ci && npm run package",
"validate:deep": "cd ahk2 && npm run validate && cd .. && npm run validate",
"validate:fix": "npm run lint:fix && npm run test && npm run package",
"vscode:prepublish": "npm run compile:grammar && npm run build && echo Packaging..."
"vscode:prepublish": "npm run build && echo Packaging..."
},
"contributes": {
"breakpoints": [
Expand Down
2 changes: 1 addition & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "Check whether non-dynamic members of a class exist",
"ahk++.config.v2.diagnostics.paramsCheck": "Check that the function call has the correct number of arguments",
"ahk++.config.v2.file.interpreterPath": "Path to the `AutoHotkey.exe` executable file for AHK v2.",
"ahk++.config.exclude": "[Glob patterns](<https://en.wikipedia.org/wiki/Glob_(programming)>) for excluding files and folders. Applies even when files are opened. Changes take effect after restart.",
"ahk++.config.exclude": "[Glob patterns](<https://en.wikipedia.org/wiki/Glob_(programming)>) for excluding files and folders from completion suggestions. Applies even when files are opened.",
"ahk++.config.v2.file.maxScanDepth": "Depth of folders to scan for IntelliSense. Negative values mean infinite depth.",
"ahk++.config.v2.librarySuggestions": "Which libraries to suggest functions from, if any. In case of issues, restart your IDE.",
"ahk++.config.v2.symbolFoldingFromOpenBrace": "Fold parameter lists separately from definitions.",
Expand Down
12 changes: 12 additions & 0 deletions src/common/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export enum ConfigKey {
compileIcon = 'compiler.compileIcon',
compilerPath = 'compiler.compilerPath',
exclude = 'exclude',
general = 'general',
generalV2 = 'v2.general',
helpPathV1 = 'v1.file.helpPath',
helpPathV2 = 'v2.file.helpPath',
indentCodeAfterIfDirective = 'v1.formatter.indentCodeAfterIfDirective',
Expand All @@ -61,3 +63,13 @@ export enum LanguageId {
ahk1 = 'ahk',
ahk2 = 'ahk2',
}

/** Defined in package.json */
export type ShowOutput = 'always' | 'never';

export enum LibIncludeType {
Disabled = 'Off',
Local = 'Local',
UserAndStandard = 'User and Standard',
All = 'All',
}
14 changes: 12 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as vscode from 'vscode';
import { ProviderResult } from 'vscode';
import { Parser } from './parser/parser';
import { clearCache, Parser } from './parser/parser';
import { RunnerService } from './service/runnerService';
import { DebugSession } from './debugger/debugSession';
import { DefProvider } from './providers/defProvider';
Expand All @@ -10,7 +10,7 @@ import { SymbolProvider } from './providers/symbolProvider';
import { FileManager } from './common/fileManager';
import { AhkHoverProvider } from './providers/ahkHoverProvider';
import { RefProvider } from './providers/refProvider';
import { Global } from './common/global';
import { ConfigKey, configPrefix, Global } from './common/global';
import { AhkRenameProvider } from './providers/ahkRenameProvider';
import { SignatureProvider } from './providers/signatureProvider';
import { CompletionProvider } from './providers/completionProvider';
Expand Down Expand Up @@ -84,6 +84,16 @@ export function activate(context: vscode.ExtensionContext) {
),
);

vscode.workspace.onDidChangeConfiguration(async (e) => {
if (!e.affectsConfiguration(`${configPrefix}.${ConfigKey.exclude}`))
return;

clearCache();
await Parser.buildByPath(
vscode.workspace.workspaceFolders?.[0].uri.fsPath,
);
});

activateV2(context);
}

Expand Down
43 changes: 23 additions & 20 deletions src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import { Script, Method, Ref, Label, Block, Variable } from './model';
import { pathsToBuild } from './parser.utils';
import { Out } from '../common/out';

const startBlockComment = / *\/\*/;
const endBlockComment = / *\*\//;
const documentCache = new Map<string, Script>();

export const clearCache = () => {
Out.debug('Clearing cache');
documentCache.clear();
};

export interface BuildScriptOptions {
/** Defaults to false. If true, short-circuits when document is in cache. */
usingCache?: boolean;
Expand All @@ -14,10 +23,8 @@ export interface BuildScriptOptions {

/** Parses v1 files */
export class Parser {
private static documentCache = new Map<string, Script>();

/**
* load method list by path
* Load method list by path
* @param buildPath
*/
public static async buildByPath(buildPath: string) {
Expand Down Expand Up @@ -46,8 +53,8 @@ export class Parser {
document: vscode.TextDocument,
options: BuildScriptOptions = {},
): Promise<Script> {
if (options.usingCache && this.documentCache.get(document.uri.path)) {
return this.documentCache.get(document.uri.path);
if (options.usingCache && documentCache.get(document.uri.path)) {
return documentCache.get(document.uri.path);
}

const maxParseLength =
Expand Down Expand Up @@ -128,7 +135,7 @@ export class Parser {
}
}
const script: Script = { methods, labels, refs, variables, blocks };
this.documentCache.set(document.uri.path, script);
documentCache.set(document.uri.path, script);
return script;
}

Expand All @@ -137,14 +144,13 @@ export class Parser {
name: string,
) {
name = name.toLowerCase();
for (const method of this.documentCache.get(document.uri.path)
.methods) {
for (const method of documentCache.get(document.uri.path).methods) {
if (method.name.toLowerCase() === name) {
return method;
}
}
for (const filePath of this.documentCache.keys()) {
for (const method of this.documentCache.get(filePath).methods) {
for (const filePath of documentCache.keys()) {
for (const method of documentCache.get(filePath).methods) {
if (method.name.toLowerCase() === name) {
return method;
}
Expand All @@ -155,8 +161,8 @@ export class Parser {

public static async getAllMethod(): Promise<Method[]> {
const methods = [];
for (const filePath of this.documentCache.keys()) {
for (const method of this.documentCache.get(filePath).methods) {
for (const filePath of documentCache.keys()) {
for (const method of documentCache.get(filePath).methods) {
methods.push(method);
}
}
Expand All @@ -168,13 +174,13 @@ export class Parser {
name: string,
) {
name = name.toLowerCase();
for (const label of this.documentCache.get(document.uri.path).labels) {
for (const label of documentCache.get(document.uri.path).labels) {
if (label.name.toLowerCase() === name) {
return label;
}
}
for (const filePath of this.documentCache.keys()) {
for (const label of this.documentCache.get(filePath).labels) {
for (const filePath of documentCache.keys()) {
for (const label of documentCache.get(filePath).labels) {
if (label.name.toLowerCase() === name) {
return label;
}
Expand All @@ -186,8 +192,8 @@ export class Parser {
public static getAllRefByName(name: string): Ref[] {
const refs = [];
name = name.toLowerCase();
for (const filePath of this.documentCache.keys()) {
const document = this.documentCache.get(filePath);
for (const filePath of documentCache.keys()) {
const document = documentCache.get(filePath);
for (const ref of document.refs) {
if (ref.name.toLowerCase() === name) {
refs.push(ref);
Expand Down Expand Up @@ -388,6 +394,3 @@ export class Parser {
}
}
}

const startBlockComment = / *\/\*/;
const endBlockComment = / *\*\//;
116 changes: 61 additions & 55 deletions src/test/config.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
updateConfig,
} from './utils';
import { resolve } from 'path';
import { ConfigKey, LibIncludeType, ShowOutput } from '../common/global';
import { suite, before, test } from 'mocha';

const rootPath = path.join(__dirname, '..', '..', '..');

Expand All @@ -18,14 +20,16 @@ const samplesParentPath = path.join(rootPath, 'src/test/samples');

// CI does not have AHK installed
suite('general.showOutput @ignoreCI', () => {
const before = async (show: 'always' | 'never') => {
await updateConfig('general', { showOutput: show });
const before = async (show: ShowOutput) => {
await updateConfig<{ showOutput: ShowOutput }>(ConfigKey.general, {
showOutput: show,
});
const filePath = path.join(samplesParentPath, 'ahk2.ahk2');
const doc = await getDocument(filePath);
await showDocument(doc);
};

const runTests: [name: string, show: 'always' | 'never'][] = [
const runTests: [name: string, show: ShowOutput][] = [
['always + run', 'always'],
['never + run', 'never'],
];
Expand All @@ -45,62 +49,64 @@ suite('general.showOutput @ignoreCI', () => {
});

suite('exclude', () => {
// todo can only run one test at a time as changes take effect after restart
test.skip('no exclusions', async () => {
await vscode.workspace
.getConfiguration('AHK++')
.update('exclude', [], vscode.ConfigurationTarget.Workspace);
const filePath = resolve(rootPath, './e2e/main.ahk');
const doc = await getDocument(filePath);
const editor = await showDocument(doc);
editor.insertSnippet(
new vscode.SnippetString('MyExclu')
.appendTabstop(0)
.appendText('\n'),
);
await sleep(100);
editor.selection = new vscode.Selection(0, 0, 0, 'MyExclu'.length);
await sleep(100);
/**
* These tests run in a specific order to update the config correctly
* Config does not update on v2 for speed
*/
const tests: [
name: string,
version: 1 | 2,
exclude: string[],
expected: boolean,
][] = [
['v1 no exclusions', 1, [], true],
['v2 no exclusions', 2, [], true],
['v1 exclusions', 1, ['excluded.ahk'], false],
['v2 exclusions', 2, ['excluded.ahk'], false],
['back to v1 no exclusions', 1, [], true],
['back to v2 no exclusions', 2, [], true],
];

// Get completion items
const completionItems =
await vscode.commands.executeCommand<vscode.CompletionList>(
'vscode.executeCompletionItemProvider',
doc.uri,
editor.selection.active,
);
const labels = completionItems?.items.map((i) => i.label);
assert.strictEqual(labels.includes('MyExcludedFunc'), true);
before(async () => {
await updateConfig<{ librarySuggestions: LibIncludeType }>(
ConfigKey.generalV2,
{ librarySuggestions: LibIncludeType.All },
);
});

test('exclusions', async () => {
await vscode.workspace
.getConfiguration('AHK++')
.update(
'exclude',
['excluded.ahk'],
vscode.ConfigurationTarget.Workspace,
tests.forEach(([name, version, exclude, expected]) => {
test(name, async () => {
const snippetText = 'MyExclu';
const funcName = 'MyExcludedFunc';
if (version === 1)
await updateConfig<string[]>(ConfigKey.exclude, exclude);
const filePath = resolve(rootPath, `./e2e/main.ahk${version}`);
const doc = await getDocument(filePath);
const editor = await showDocument(doc);
editor.insertSnippet(
new vscode.SnippetString(snippetText)
.appendTabstop(0)
.appendText('\n'),
);
const filePath = resolve(rootPath, './e2e/main.ahk');
const doc = await getDocument(filePath);
const editor = await showDocument(doc);
editor.insertSnippet(
new vscode.SnippetString('MyExclu')
.appendTabstop(0)
.appendText('\n'),
);
await sleep(100);
editor.selection = new vscode.Selection(0, 0, 0, 'MyExclu'.length);
await sleep(100);

// Get completion items
const completionItems =
await vscode.commands.executeCommand<vscode.CompletionList>(
'vscode.executeCompletionItemProvider',
doc.uri,
editor.selection.active,
await sleep(1_000);
editor.selection = new vscode.Selection(
0,
0,
0,
snippetText.length,
);
const labels = completionItems?.items.map((i) => i.label);
assert.strictEqual(labels.includes('MyExcludedFunc'), false);
await sleep(1_000);

// Get completion items
const completionItems =
await vscode.commands.executeCommand<vscode.CompletionList>(
'vscode.executeCompletionItemProvider',
doc.uri,
editor.selection.active,
);
await sleep(1_000);
const labels = completionItems?.items.map((i) => i.label);
assert.strictEqual(labels.includes(funcName), expected);
});
});
});
Loading

0 comments on commit dd40e6f

Please sign in to comment.