fix: diagnostics do not refresh after editing pom file (#695)
This commit is contained in:
Родитель
7856e00c8b
Коммит
38b3f420a7
|
@ -8,12 +8,14 @@
|
|||
"version": "0.32.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lru-cache": "^5.1.0",
|
||||
"axios": "^0.21.1",
|
||||
"expand-home-dir": "0.0.3",
|
||||
"fast-glob": "^3.2.7",
|
||||
"fs-extra": "^4.0.3",
|
||||
"get-port": "^4.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^6.0.0",
|
||||
"md5": "^2.2.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"semver": "^5.6.0",
|
||||
|
@ -176,6 +178,11 @@
|
|||
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw=="
|
||||
},
|
||||
"node_modules/@types/md5": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.0.tgz",
|
||||
|
@ -2523,6 +2530,17 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/map-cache": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
||||
|
@ -4320,17 +4338,6 @@
|
|||
"vscode": "^1.52.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
|
@ -4345,11 +4352,6 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/vscode-languageserver-protocol": {
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz",
|
||||
|
@ -4712,6 +4714,11 @@
|
|||
"integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "13.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
|
||||
|
@ -4880,6 +4887,11 @@
|
|||
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw=="
|
||||
},
|
||||
"@types/md5": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.0.tgz",
|
||||
|
@ -6748,6 +6760,14 @@
|
|||
"chalk": "^2.4.2"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"map-cache": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
||||
|
@ -8144,14 +8164,6 @@
|
|||
"vscode-languageserver-protocol": "3.16.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
|
@ -8159,11 +8171,6 @@
|
|||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -8453,6 +8460,11 @@
|
|||
"integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "13.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
|
||||
|
|
|
@ -705,12 +705,14 @@
|
|||
"webpack-cli": "^3.3.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lru-cache": "^5.1.0",
|
||||
"axios": "^0.21.1",
|
||||
"expand-home-dir": "0.0.3",
|
||||
"fast-glob": "^3.2.7",
|
||||
"fs-extra": "^4.0.3",
|
||||
"get-port": "^4.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^6.0.0",
|
||||
"md5": "^2.2.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"semver": "^5.6.0",
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
import * as fse from "fs-extra";
|
||||
import * as _ from "lodash";
|
||||
import { performance } from "perf_hooks";
|
||||
import * as vscode from "vscode";
|
||||
import { getRequestDelay, lruCache, MovingAverage } from "./debouncing";
|
||||
import { mavenExplorerProvider } from "./explorer/mavenExplorerProvider";
|
||||
import { Dependency } from "./explorer/model/Dependency";
|
||||
import { MavenProject } from "./explorer/model/MavenProject";
|
||||
import { UserError } from "./utils/errorUtils";
|
||||
import { ElementNode, getNodesByTag, XmlTagName } from "./utils/lexerUtils";
|
||||
|
||||
|
@ -16,22 +20,44 @@ class DiagnosticProvider {
|
|||
const dependencyCollection = vscode.languages.createDiagnosticCollection("Dependency");
|
||||
this._collection = dependencyCollection;
|
||||
context.subscriptions.push(this._collection);
|
||||
context.subscriptions.push(vscode.workspace.onDidCloseTextDocument(doc => {
|
||||
dependencyCollection.delete(doc.uri);
|
||||
this.map.clear();
|
||||
context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(
|
||||
async e => {
|
||||
if (e.document.fileName.endsWith("pom.xml")) {
|
||||
await this.debouncedRefresh(e.document.uri);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public async refreshDiagnostics(uri: vscode.Uri, conflictNodes: Dependency[]): Promise<vscode.Diagnostic[]> {
|
||||
this.map.clear();
|
||||
private updateNodeForDocumentTimeout: NodeJS.Timer;
|
||||
private async debouncedRefresh(uri: vscode.Uri): Promise<void> {
|
||||
if (this.updateNodeForDocumentTimeout) {
|
||||
clearTimeout(this.updateNodeForDocumentTimeout);
|
||||
}
|
||||
const timeout: number = getRequestDelay(uri);
|
||||
this.updateNodeForDocumentTimeout = setTimeout(async () => {
|
||||
const startTime: number = performance.now();
|
||||
await this.refreshDiagnostics(uri);
|
||||
const executionTime: number = performance.now() - startTime;
|
||||
const movingAverage: MovingAverage = lruCache.get(uri) || new MovingAverage();
|
||||
movingAverage.update(executionTime);
|
||||
lruCache.set(uri, movingAverage);
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
public async refreshDiagnostics(uri: vscode.Uri): Promise<void> {
|
||||
const diagnostics: vscode.Diagnostic[] = [];
|
||||
const project: MavenProject | undefined = mavenExplorerProvider.getMavenProject(uri.fsPath);
|
||||
if (project === undefined) {
|
||||
throw new Error("Failed to get maven project.");
|
||||
}
|
||||
|
||||
const conflictNodes: Dependency[] = project.conflictNodes;
|
||||
for (const node of conflictNodes) {
|
||||
const diagnostic = await this.createDiagnostics(node);
|
||||
diagnostics.push(diagnostic);
|
||||
this.map.set(diagnostic, node);
|
||||
}
|
||||
this._collection.set(uri, diagnostics);
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public async createDiagnostics(node: Dependency): Promise<vscode.Diagnostic> {
|
||||
|
@ -44,8 +70,8 @@ class DiagnosticProvider {
|
|||
}
|
||||
|
||||
public async findConflictRange(filePath: string, gid: string, aid: string): Promise<vscode.Range> {
|
||||
const contentBuf: Buffer = await fse.readFile(filePath);
|
||||
const projectNodes: ElementNode[] = getNodesByTag(contentBuf.toString(), XmlTagName.Project);
|
||||
const pomDocument = await vscode.window.showTextDocument(vscode.Uri.file(filePath), {preserveFocus: true});
|
||||
const projectNodes: ElementNode[] = getNodesByTag(pomDocument.document.getText(), XmlTagName.Project);
|
||||
if (projectNodes === undefined || projectNodes.length !== 1) {
|
||||
throw new UserError("Only support POM file with single <project> node.");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as LRUCache from "lru-cache";
|
||||
import * as vscode from "vscode";
|
||||
|
||||
export const lruCache: LRUCache<vscode.Uri, MovingAverage> = new LRUCache<vscode.Uri, MovingAverage>(32);
|
||||
|
||||
// See: https://github.com/microsoft/vscode/blob/94c9ea46838a9a619aeafb7e8afd1170c967bb55/src/vs/base/common/numbers.ts
|
||||
export class MovingAverage {
|
||||
|
||||
private _n: number = 1;
|
||||
private _val: number = 0;
|
||||
|
||||
public update(value: number): this {
|
||||
this._val = this._val + (value - this._val) / this._n;
|
||||
this._n += 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public get value(): number {
|
||||
return this._val;
|
||||
}
|
||||
}
|
||||
|
||||
export function getRequestDelay(uri: vscode.Uri): number {
|
||||
const avg: MovingAverage | undefined = lruCache.get(uri);
|
||||
if (!avg) {
|
||||
return 350;
|
||||
}
|
||||
// See: https://github.com/microsoft/vscode/blob/94c9ea46838a9a619aeafb7e8afd1170c967bb55/src/vs/editor/common/modes/languageFeatureRegistry.ts#L204
|
||||
return Math.max(350, Math.floor(1.3 * avg.value));
|
||||
}
|
|
@ -22,8 +22,8 @@ export class DependenciesMenu extends Menu implements ITreeItem {
|
|||
}
|
||||
|
||||
public async getChildren() : Promise<Dependency[] | HintNode[]> {
|
||||
const [treeNodes, conflictNodes] = await parseRawDependencyDataHandler(this.project);
|
||||
await diagnosticProvider.refreshDiagnostics(vscode.Uri.file(this.project.pomPath), conflictNodes);
|
||||
const treeNodes = await parseRawDependencyDataHandler(this.project);
|
||||
await diagnosticProvider.refreshDiagnostics(vscode.Uri.file(this.project.pomPath));
|
||||
if (treeNodes.length === 0) {
|
||||
const hintNodes: HintNode[] = [new HintNode("No dependencies")];
|
||||
return Promise.resolve(hintNodes);
|
||||
|
|
|
@ -12,6 +12,7 @@ import { Utils } from "../../utils/Utils";
|
|||
import { EffectivePomProvider } from "../EffectivePomProvider";
|
||||
import { mavenExplorerProvider } from "../mavenExplorerProvider";
|
||||
import { DependenciesMenu} from "./DependenciesMenu";
|
||||
import { Dependency } from "./Dependency";
|
||||
import { IEffectivePom } from "./IEffectivePom";
|
||||
import { ITreeItem } from "./ITreeItem";
|
||||
import { LifecycleMenu } from "./LifecycleMenu";
|
||||
|
@ -24,6 +25,7 @@ export class MavenProject implements ITreeItem {
|
|||
public parent?: MavenProject; // assigned if it's specified as one of parent project's modules
|
||||
public pomPath: string;
|
||||
public _fullDependencyText: string;
|
||||
public conflictNodes: Dependency[];
|
||||
private ePomProvider: EffectivePomProvider;
|
||||
private _ePom: any;
|
||||
private _pom: any;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { getDependencyTree } from "../handlers/showDependenciesHandler";
|
|||
const DUPLICATE_INDICATOR: string = "omitted for duplicate";
|
||||
const CONFLICT_INDICATOR: string = "omitted for conflict";
|
||||
|
||||
export async function parseRawDependencyDataHandler(project: MavenProject): Promise<Dependency[][]> {
|
||||
export async function parseRawDependencyDataHandler(project: MavenProject): Promise<Dependency[]> {
|
||||
const dependencyTree: string | undefined = await getDependencyTree(project.pomPath);
|
||||
if (dependencyTree === undefined) {
|
||||
throw new Error("Failed to generate dependency tree.");
|
||||
|
@ -30,7 +30,9 @@ export async function parseRawDependencyDataHandler(project: MavenProject): Prom
|
|||
const indent: string = " "; // three spaces
|
||||
const eol: string = "\r\n";
|
||||
const prefix: string = "+- ";
|
||||
return await parseTreeNodes(treeContent, eol, indent, prefix, project.pomPath);
|
||||
const [treeNodes, conflictNodes] = await parseTreeNodes(treeContent, eol, indent, prefix, project.pomPath);
|
||||
project.conflictNodes = conflictNodes;
|
||||
return treeNodes;
|
||||
}
|
||||
|
||||
async function parseTreeNodes(treecontent: string, eol: string, indent: string, prefix: string, projectPomPath: string): Promise<Dependency[][]> {
|
||||
|
|
Загрузка…
Ссылка в новой задаче