refactor: add effective pom provider (#400)

* rename member variables

* refactor: add effective pom provider

* fix errors

* update changelog
This commit is contained in:
Yan Zhang 2019-09-18 15:49:10 +08:00 коммит произвёл GitHub
Родитель 45f4d55248
Коммит 9dbc2be245
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 132 добавлений и 82 удалений

Просмотреть файл

@ -7,6 +7,7 @@ All notable changes to the "vscode-maven" extension will be documented in this f
#### Fixed
- Cannot show dependencies.
- Expanded plugin nodes tend to collapse after loading. [#364](https://github.com/microsoft/vscode-maven/issues/364)
## 0.18.2
#### Fixed

Просмотреть файл

@ -0,0 +1,71 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { EventEmitter } from "events";
import { rawEffectivePom } from "../utils/mavenUtils";
import { Utils } from "../utils/Utils";
import { IEffectivePom } from "./model/IEffectivePom";
export class EffectivePomProvider {
private pomPath: string;
private effectivePom: IEffectivePom;
private emitter: EventEmitter = new EventEmitter();
private isCaculating: boolean = false;
constructor(pomPath: string) {
this.pomPath = pomPath;
this.emitter.on("complete", (resp: IEffectivePom) => {
this.effectivePom = resp;
this.isCaculating = false;
});
this.emitter.on("error", (_error) => {
this.effectivePom = { pomPath };
this.isCaculating = false;
});
}
public async calculateEffectivePom(): Promise<void> {
if (this.isCaculating) {
return new Promise<void>((resolve, reject) => {
this.emitter.once("complete", resolve);
this.emitter.once("error", reject);
});
}
const pomPath: string = this.pomPath;
try {
this.isCaculating = true;
const ePomString: string | undefined = await rawEffectivePom(pomPath);
const ePom: any = await Utils.parseXmlContent(ePomString ? ePomString : "");
this.emitter.emit("complete", {
pomPath,
ePomString,
ePom
});
} catch (error) {
this.emitter.emit("error", error);
}
}
public async getEffectivePom(): Promise<IEffectivePom> {
const promise: Promise<IEffectivePom> = new Promise<IEffectivePom>((resolve, reject) => {
this.emitter.once("complete", (resp: IEffectivePom) => {
resolve(resp);
});
this.emitter.once("error", (error) => {
reject(error);
});
});
if (this.isCaculating) {
return promise;
}
if (this.effectivePom) {
return this.effectivePom;
}
this.calculateEffectivePom().catch(console.error);
return promise;
}
}

Просмотреть файл

@ -1,41 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { rawEffectivePom } from "../../utils/mavenUtils";
import { Utils } from "../../utils/Utils";
export class EffectivePom {
public pomPath: string;
public raw: string | undefined;
public data: any;
public upToDate: boolean;
private _updating: boolean;
constructor(pomPath: string) {
this.pomPath = pomPath;
this._updating = false;
this.upToDate = false;
}
/**
* Generate effective pom and parse the data
*/
public async update(silent?: boolean): Promise<void> {
if (this._updating) {
return;
}
this._updating = true;
try {
this.raw = silent ? await rawEffectivePom(this.pomPath) : await Utils.getEffectivePom(this.pomPath);
this.data = await Utils.parseXmlContent(this.raw ? this.raw : "");
this.upToDate = true;
} catch (error) {
throw error;
} finally {
this._updating = false;
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export interface IEffectivePom {
pomPath: string;
ePomString?: string;
ePom?: any;
}

Просмотреть файл

@ -9,8 +9,9 @@ import { Settings } from "../../Settings";
import { taskExecutor } from "../../taskExecutor";
import { getPathToExtensionRoot } from "../../utils/contextUtils";
import { Utils } from "../../utils/Utils";
import { EffectivePomProvider } from "../EffectivePomProvider";
import { mavenExplorerProvider } from "../mavenExplorerProvider";
import { EffectivePom } from "./EffectivePom";
import { IEffectivePom } from "./IEffectivePom";
import { ITreeItem } from "./ITreeItem";
import { MavenPlugin } from "./MavenPlugin";
import { PluginsMenu } from "./PluginsMenu";
@ -19,14 +20,15 @@ const CONTEXT_VALUE: string = "MavenProject";
export class MavenProject implements ITreeItem {
public parent?: MavenProject;
private _effectivePom: EffectivePom;
public pomPath: string;
private ePomProvider: EffectivePomProvider;
private _ePom: any;
private _pom: any;
private _pomPath: string;
constructor(pomPath: string) {
this._pomPath = pomPath;
this._effectivePom = new EffectivePom(pomPath);
taskExecutor.execute(async () => await this._effectivePom.update(true));
this.pomPath = pomPath;
this.ePomProvider = new EffectivePomProvider(pomPath);
taskExecutor.execute(async () => await this.ePomProvider.calculateEffectivePom());
}
public get name(): string {
@ -42,31 +44,42 @@ export class MavenProject implements ITreeItem {
return moduleNames ? moduleNames : [];
}
public get effectivePom(): EffectivePom {
return this._effectivePom;
}
public get plugins(): MavenPlugin[] {
let plugins: any[] | undefined;
if (_.has(this._effectivePom.data, "projects.project")) {
if (_.has(this._ePom, "projects.project")) {
// multi-module project
const project: any = (<any[]>this._effectivePom.data.projects.project).find((elem: any) => this.name === _.get(elem, "artifactId[0]"));
const project: any = (<any[]>this._ePom.projects.project).find((elem: any) => this.name === _.get(elem, "artifactId[0]"));
if (project) {
plugins = _.get(project, "build[0].plugins[0].plugin");
}
} else {
// single-project
plugins = _.get(this._effectivePom.data, "project.build[0].plugins[0].plugin");
plugins = _.get(this._ePom, "project.build[0].plugins[0].plugin");
}
return this._convertXmlPlugin(plugins);
}
public get dependencies(): any[] {
let deps: any[] | undefined;
if (_.has(this._ePom, "projects.project")) {
// multi-module project
const project: any = (<any[]>this._ePom.projects.project).find((elem: any) => this.name === _.get(elem, "artifactId[0]"));
if (project) {
deps = _.get(project, "build[0].plugins[0].plugin");
}
} else {
// single-project
deps = _.get(this._ePom, "project.dependencies[0].dependency");
}
return deps || [];
}
/**
* @return list of absolute path of modules pom.xml.
*/
public get modules(): string[] {
return this.moduleNames.map(moduleName => {
const relative: string = path.join(path.dirname(this._pomPath), moduleName);
const relative: string = path.join(path.dirname(this.pomPath), moduleName);
if (fs.existsSync(relative) && fs.statSync(relative).isFile()) {
return relative;
} else {
@ -75,10 +88,6 @@ export class MavenProject implements ITreeItem {
});
}
public get pomPath(): string {
return this._pomPath;
}
public async getTreeItem(): Promise<vscode.TreeItem> {
await this.parsePom();
const label: string = this.name ? this.name : "[Corrupted]";
@ -106,19 +115,19 @@ export class MavenProject implements ITreeItem {
return ret;
}
public async calculateEffectivePom(force?: boolean): Promise<string | undefined> {
if (!force && this._effectivePom.upToDate) {
return this._effectivePom.raw;
}
public async refreshEffectivePom(): Promise<void> {
await this.ePomProvider.calculateEffectivePom();
}
public async getEffectivePom(): Promise<IEffectivePom> {
let res: IEffectivePom = { pomPath: this.pomPath };
try {
await this._effectivePom.update();
mavenExplorerProvider.refresh(this);
return this._effectivePom.raw;
res = await this.ePomProvider.getEffectivePom();
this._ePom = res.ePom;
} catch (error) {
console.error(error);
return this._effectivePom.raw;
}
return res;
}
public async refresh(): Promise<void> {
@ -127,7 +136,7 @@ export class MavenProject implements ITreeItem {
public async parsePom(): Promise<void> {
try {
this._pom = await Utils.parseXmlFile(this._pomPath);
this._pom = await Utils.parseXmlFile(this.pomPath);
} catch (error) {
this._pom = undefined;
}

Просмотреть файл

@ -9,11 +9,11 @@ import { MavenProject } from "./MavenProject";
const CONTEXT_VALUE: string = "Menu";
export abstract class Menu implements ITreeItem {
protected _project: MavenProject;
protected _name: string;
protected project: MavenProject;
protected name: string;
constructor(project: MavenProject) {
this._project = project;
this.project = project;
}
public abstract getChildren(): ITreeItem[] | undefined | Promise<ITreeItem[] | undefined>;
@ -23,7 +23,7 @@ export abstract class Menu implements ITreeItem {
}
public getTreeItem(): vscode.TreeItem | Thenable<vscode.TreeItem> {
const treeItem: vscode.TreeItem = new vscode.TreeItem(this._name, vscode.TreeItemCollapsibleState.Collapsed);
const treeItem: vscode.TreeItem = new vscode.TreeItem(this.name, vscode.TreeItemCollapsibleState.Collapsed);
treeItem.iconPath = {
light: getPathToExtensionRoot("resources", "icons", "light", "folder.svg"),
dark: getPathToExtensionRoot("resources", "icons", "dark", "folder.svg")

Просмотреть файл

@ -12,11 +12,11 @@ import { Menu } from "./Menu";
export class ModulesMenu extends Menu implements ITreeItem {
constructor(projectNode: MavenProject) {
super(projectNode);
this._name = "Modules";
this.name = "Modules";
}
public getChildren() : MavenProject[] {
return this._project.modules.map(modulePomPath => {
return this.project.modules.map(modulePomPath => {
const found: MavenProject | undefined = mavenExplorerProvider.getMavenProject(modulePomPath);
return found ? found : new MavenProject(modulePomPath);
});

Просмотреть файл

@ -12,16 +12,16 @@ import { Menu } from "./Menu";
export class PluginsMenu extends Menu implements ITreeItem {
constructor(project: MavenProject) {
super(project);
this._name = "Plugins";
this.name = "Plugins";
}
public async getChildren() : Promise<MavenPlugin[]> {
await this._project.calculateEffectivePom();
return this._project.plugins;
await this.project.getEffectivePom();
return this.project.plugins;
}
public getTreeItem(): vscode.TreeItem | Thenable<vscode.TreeItem> {
const treeItem: vscode.TreeItem = new vscode.TreeItem(this._name, vscode.TreeItemCollapsibleState.Collapsed);
const treeItem: vscode.TreeItem = new vscode.TreeItem(this.name, vscode.TreeItemCollapsibleState.Collapsed);
treeItem.iconPath = {
light: getPathToExtensionRoot("resources", "icons", "light", "extensions.svg"),
dark: getPathToExtensionRoot("resources", "icons", "dark", "extensions.svg")
@ -30,7 +30,7 @@ export class PluginsMenu extends Menu implements ITreeItem {
}
public async refresh(): Promise<void> {
this._project.effectivePom.upToDate = false;
this.project.refreshEffectivePom().catch(console.error);
mavenExplorerProvider.refresh(this);
}
}

Просмотреть файл

@ -160,7 +160,7 @@ function registerPomFileWatcher(context: vscode.ExtensionContext): void {
await project.refresh();
if (Settings.Pomfile.autoUpdateEffectivePOM()) {
taskExecutor.execute(async () => {
await project.effectivePom.update();
await project.refreshEffectivePom();
mavenExplorerProvider.refresh(project);
});
}

Просмотреть файл

@ -47,7 +47,7 @@ function getEffectiveVersion(uri: vscode.Uri, gid: string, aid: string): string
return undefined;
}
const deps: {}[] = _.get(mavenProject.effectivePom.data, "project.dependencies[0].dependency", []);
const deps: {}[] = mavenProject.dependencies;
const targetDep: {} | undefined = deps.find(elem => _.get(elem, "groupId[0]") === gid && _.get(elem, "artifactId[0]") === aid);
return targetDep && _.get(targetDep, "version[0]");

Просмотреть файл

@ -10,6 +10,7 @@ import { commands, Progress, ProgressLocation, RelativePattern, TextDocument, Ur
import { createUuid, setUserError } from "vscode-extension-telemetry-wrapper";
import * as xml2js from "xml2js";
import { mavenExplorerProvider } from "../explorer/mavenExplorerProvider";
import { IEffectivePom } from "../explorer/model/IEffectivePom";
import { MavenProject } from "../explorer/model/MavenProject";
import { Settings } from "../Settings";
import { getExtensionVersion, getPathToTempFolder, getPathToWorkspaceStorage } from "./contextUtils";
@ -121,7 +122,8 @@ export namespace Utils {
let pomxml: string | undefined;
const project: MavenProject | undefined = mavenExplorerProvider.getMavenProject(pomPath);
if (project) {
pomxml = await project.calculateEffectivePom();
const effectivePom: IEffectivePom = await project.getEffectivePom();
pomxml = effectivePom.ePomString;
} else {
pomxml = await getEffectivePom(pomPath);
}