Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect exclude without requiring restart #545

Merged
merged 6 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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