Add go-to-effective command to conflict dependencies (#716)
This commit is contained in:
Родитель
ebe8c8034e
Коммит
60c5412d67
14
package.json
14
package.json
|
@ -210,6 +210,11 @@
|
|||
"category": "Maven",
|
||||
"icon": "$(wrench)"
|
||||
},
|
||||
{
|
||||
"command": "maven.dependency.goToEffective",
|
||||
"title": "%contributes.commands.maven.dependency.goToEffective%",
|
||||
"category": "Maven"
|
||||
},
|
||||
{
|
||||
"command": "maven.project.goToDefinition",
|
||||
"title": "%contributes.commands.maven.project.goToDefinition%",
|
||||
|
@ -321,6 +326,10 @@
|
|||
"command": "maven.project.setDependencyVersion",
|
||||
"when": "never"
|
||||
},
|
||||
{
|
||||
"command": "maven.dependency.goToEffective",
|
||||
"when": "never"
|
||||
},
|
||||
{
|
||||
"command": "maven.project.goToDefinition",
|
||||
"when": "never"
|
||||
|
@ -457,6 +466,11 @@
|
|||
"when": "view == mavenProjects && viewItem =~ /maven:dependency(?=.*?\\b\\+conflict\\b)/",
|
||||
"group": "inline"
|
||||
},
|
||||
{
|
||||
"command": "maven.dependency.goToEffective",
|
||||
"when": "view == mavenProjects && viewItem =~ /maven:dependency(?=.*?\\b\\+conflict\\b)/",
|
||||
"group": "0-dependency@2"
|
||||
},
|
||||
{
|
||||
"command": "maven.project.goToDefinition",
|
||||
"when": "view == mavenProjects && viewItem =~ /maven:dependency/",
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
"contributes.commands.maven.view.hierarchical": "Switch to hierarchical view",
|
||||
"contributes.commands.maven.view.flat": "Switch to flat view",
|
||||
"contributes.commands.maven.project.addDependency": "Add a dependency...",
|
||||
"contributes.commands.maven.project.showDependencies": "Show dependencies",
|
||||
"contributes.commands.maven.project.excludeDependency": "Exclude dependency",
|
||||
"contributes.commands.maven.project.setDependencyVersion": "Resolve conflict...",
|
||||
"contributes.commands.maven.project.showDependencies": "Show Dependencies",
|
||||
"contributes.commands.maven.project.excludeDependency": "Exclude Dependency",
|
||||
"contributes.commands.maven.project.setDependencyVersion": "Resolve Conflict...",
|
||||
"contributes.commands.maven.dependency.goToEffective": "Go to Effective Dependency",
|
||||
"contributes.commands.maven.project.goToDefinition": "Go to Definition",
|
||||
"contributes.views.explorer.mavenProjects": "Maven",
|
||||
"contributes.viewsWelcome.mavenProjects.untrustedWorkspaces": "Advanced features (e.g. executing lifecycle phases and plugin goals) are disabled in Restricted Mode for security concern.\nPOM editing assistance (e.g. [add a dependency](command:maven.project.addDependency)) is still available.\nLearn more about [Workspace Trust](https://aka.ms/vscode-workspace-trust).\n[Manage Workspace Trust](command:workbench.action.manageTrust)",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"contributes.commands.maven.project.goToDefinition": "转到定义",
|
||||
"contributes.commands.maven.project.excludeDependency": "删除依赖",
|
||||
"contributes.commands.maven.project.setDependencyVersion": "指定依赖版本为...",
|
||||
"contributes.commands.maven.dependency.goToEffective": "转到有效的依赖项",
|
||||
"contributes.views.explorer.mavenProjects": "Maven",
|
||||
"configuration.maven.excludedFolders": "指定搜索 Maven 项目时要排除的文件夹。",
|
||||
"configuration.maven.executable.preferMavenWrapper": "指定是否优先使用 Maven Wrapper。如果为 true,则尝试向上遍历父文件夹寻找 mvnw 作为可执行文件;如果为 false,或者找不到 mvnw,则尝试使用系统 PATH 中的 mvn。",
|
||||
|
|
|
@ -66,7 +66,7 @@ class DiagnosticProvider {
|
|||
}
|
||||
|
||||
public async createDiagnostics(node: Dependency): Promise<vscode.Diagnostic> {
|
||||
const root: Dependency = <Dependency> node.root;
|
||||
const root: Dependency = node.root;
|
||||
const range: vscode.Range = await this.findConflictRange(root.projectPomPath, root.groupId, root.artifactId);
|
||||
const message: string = `Dependency conflict in ${root.artifactId}: ${node.groupId}:${node.artifactId}:${node.version} conflict with ${node.omittedStatus?.effectiveVersion}`;
|
||||
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Warning);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { TreeDataProvider } from "vscode";
|
||||
import * as vscode from "vscode";
|
||||
import { Utils } from "../utils/Utils";
|
||||
import { Dependency } from "./model/Dependency";
|
||||
import { ITreeItem } from "./model/ITreeItem";
|
||||
import { MavenProject } from "./model/MavenProject";
|
||||
import { WorkspaceFolder } from "./model/WorkspaceFolder";
|
||||
|
@ -80,6 +81,13 @@ class MavenExplorerProvider implements TreeDataProvider<ITreeItem> {
|
|||
return element.getChildren ? element.getChildren() : undefined;
|
||||
}
|
||||
}
|
||||
public async getParent(element: ITreeItem): Promise<ITreeItem | undefined> {
|
||||
if (element instanceof Dependency) {
|
||||
return element.parent;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public refresh(item?: ITreeItem): void {
|
||||
this._onDidChangeTreeData.fire(item);
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
import * as vscode from "vscode";
|
||||
import { ITreeItem } from "./ITreeItem";
|
||||
import { ITreeNode } from "./ITreeNode";
|
||||
import { IOmittedStatus } from "./OmittedStatus";
|
||||
import { TreeNode } from "./TreeNode";
|
||||
|
||||
export class Dependency extends TreeNode implements ITreeItem {
|
||||
export class Dependency implements ITreeItem, ITreeNode {
|
||||
public fullArtifactName: string = ""; // groupId:artifactId:version:scope
|
||||
public projectPomPath: string;
|
||||
public groupId: string;
|
||||
|
@ -15,8 +15,10 @@ export class Dependency extends TreeNode implements ITreeItem {
|
|||
public scope: string;
|
||||
public omittedStatus?: IOmittedStatus;
|
||||
public uri: vscode.Uri;
|
||||
public children: Dependency[] = [];
|
||||
public root: Dependency;
|
||||
public parent: Dependency;
|
||||
constructor(gid: string, aid: string, version: string, scope: string, projectPomPath: string, omittedStatus?: IOmittedStatus) {
|
||||
super();
|
||||
this.groupId = gid;
|
||||
this.artifactId = aid;
|
||||
this.version = version;
|
||||
|
@ -26,8 +28,13 @@ export class Dependency extends TreeNode implements ITreeItem {
|
|||
this.omittedStatus = omittedStatus;
|
||||
}
|
||||
|
||||
public addChild(node: Dependency): void {
|
||||
node.parent = this;
|
||||
this.children.push(node);
|
||||
}
|
||||
|
||||
public getContextValue(): string {
|
||||
const root = <Dependency> this.root;
|
||||
const root = this.root;
|
||||
let contextValue: string = "maven:dependency";
|
||||
if (root.fullArtifactName === this.fullArtifactName) {
|
||||
contextValue = `${contextValue}+root`;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export interface ITreeNode {
|
||||
children: ITreeNode[];
|
||||
parent?: ITreeNode | undefined;
|
||||
root?: ITreeNode | undefined;
|
||||
|
||||
addChild(node: ITreeNode): void;
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ export class MavenProject implements ITreeItem {
|
|||
public pomPath: string;
|
||||
public _fullDependencyText: string;
|
||||
public conflictNodes: Dependency[];
|
||||
public dependencyNodes: Dependency[];
|
||||
private ePomProvider: EffectivePomProvider;
|
||||
private _ePom: any;
|
||||
private _pom: any;
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export class TreeNode {
|
||||
public children: TreeNode[] = [];
|
||||
public parent?: TreeNode | undefined;
|
||||
public root?: TreeNode | undefined;
|
||||
|
||||
public addChild(node: TreeNode): void {
|
||||
node.parent = this;
|
||||
this.children.push(node);
|
||||
}
|
||||
|
||||
public addChildren(nodes: TreeNode[]): void {
|
||||
nodes.forEach(node => node.parent = this);
|
||||
this.children = this.children.concat(nodes);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import { diagnosticProvider } from "./DiagnosticProvider";
|
|||
import { initExpService } from "./experimentationService";
|
||||
import { decorationProvider } from "./explorer/decorationProvider";
|
||||
import { mavenExplorerProvider } from "./explorer/mavenExplorerProvider";
|
||||
import { Dependency } from "./explorer/model/Dependency";
|
||||
import { ITreeItem } from "./explorer/model/ITreeItem";
|
||||
import { MavenProject } from "./explorer/model/MavenProject";
|
||||
import { PluginGoal } from "./explorer/model/PluginGoal";
|
||||
|
@ -24,6 +25,7 @@ import { pluginInfoProvider } from "./explorer/pluginInfoProvider";
|
|||
import { addDependencyHandler } from "./handlers/addDependencyHandler";
|
||||
import { debugHandler } from "./handlers/debugHandler";
|
||||
import { excludeDependencyHandler } from "./handlers/excludeDependencyHandler";
|
||||
import { goToEffectiveHandler } from "./handlers/goToEffectiveHandler";
|
||||
import { jumpToDefinitionHandler } from "./handlers/jumpToDefinitionHandler";
|
||||
import { runFavoriteCommandsHandler } from "./handlers/runFavoriteCommandsHandler";
|
||||
import { setDependencyVersionHandler } from "./handlers/setDependencyVersionHandler";
|
||||
|
@ -59,7 +61,9 @@ async function doActivate(_operationId: string, context: vscode.ExtensionContext
|
|||
await vscode.commands.executeCommand("setContext", "vscode-maven:activated", true);
|
||||
// register tree view
|
||||
await mavenExplorerProvider.loadProjects();
|
||||
context.subscriptions.push(vscode.window.createTreeView("mavenProjects", { treeDataProvider: mavenExplorerProvider, showCollapseAll: true }));
|
||||
const view = vscode.window.createTreeView("mavenProjects", { treeDataProvider: mavenExplorerProvider, showCollapseAll: true });
|
||||
context.subscriptions.push(view);
|
||||
registerCommand(context, "maven.dependency.goToEffective", (node?: Dependency) => goToEffectiveHandler(view, node));
|
||||
context.subscriptions.push(vscode.workspace.onDidGrantWorkspaceTrust(_e => {
|
||||
mavenExplorerProvider.refresh();
|
||||
}));
|
||||
|
|
|
@ -12,7 +12,7 @@ export async function excludeDependencyHandler(toExclude?: Dependency): Promise<
|
|||
if (toExclude === undefined) {
|
||||
throw new UserError("Only Dependency can be excluded.");
|
||||
}
|
||||
const root: Dependency | undefined = toExclude.root ? <Dependency> toExclude.root : undefined;
|
||||
const root: Dependency = toExclude.root;
|
||||
if (root === undefined || toExclude.fullArtifactName === root.fullArtifactName) {
|
||||
vscode.window.showInformationMessage("The dependency written in pom can not be excluded.");
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as vscode from "vscode";
|
||||
import { mavenExplorerProvider } from "../explorer/mavenExplorerProvider";
|
||||
import { Dependency } from "../explorer/model/Dependency";
|
||||
import { ITreeItem } from "../explorer/model/ITreeItem";
|
||||
import { MavenProject } from "../explorer/model/MavenProject";
|
||||
import { Queue } from "../taskExecutor";
|
||||
|
||||
export async function goToEffectiveHandler(view: vscode.TreeView<ITreeItem>, node?: Dependency): Promise<void> {
|
||||
if (node === undefined || node.omittedStatus === undefined) {
|
||||
throw new Error("No conflict dependency node specified.");
|
||||
}
|
||||
const fullArtifactName: string = [node.groupId, node.artifactId, node.omittedStatus.effectiveVersion, node.scope].join(":");
|
||||
const pomPath: string = node.projectPomPath;
|
||||
const project: MavenProject | undefined = mavenExplorerProvider.getMavenProject(pomPath);
|
||||
if (project === undefined) {
|
||||
throw new Error("Failed to find maven projects.");
|
||||
}
|
||||
|
||||
const dependencyNodes = project.dependencyNodes;
|
||||
const treeItem: Dependency | undefined = await searchFirstEffective(dependencyNodes, fullArtifactName);
|
||||
if (treeItem === undefined) {
|
||||
throw new Error("Failed to find dependency.");
|
||||
}
|
||||
view.reveal(treeItem, { focus: true});
|
||||
|
||||
}
|
||||
|
||||
async function searchFirstEffective(dependencyNodes: Dependency[], fullArtifactName: string): Promise<Dependency | undefined> {
|
||||
let targetItem: Dependency | undefined;
|
||||
const queue: Queue<Dependency> = new Queue();
|
||||
for (const child of dependencyNodes) {
|
||||
queue.push(child);
|
||||
}
|
||||
while (queue.empty() === false) {
|
||||
const node: Dependency | undefined = queue.pop();
|
||||
if (node === undefined) {
|
||||
throw new Error("Failed to find dependency.");
|
||||
}
|
||||
if (node.fullArtifactName === fullArtifactName) {
|
||||
targetItem = node;
|
||||
break;
|
||||
}
|
||||
const children = <Dependency[]> node.children;
|
||||
for (const child of children) {
|
||||
queue.push(child);
|
||||
}
|
||||
}
|
||||
return targetItem;
|
||||
}
|
|
@ -16,7 +16,7 @@ export async function jumpToDefinitionHandler(node?: Dependency): Promise<void>
|
|||
if (node.parent === undefined) {
|
||||
selectedPath = node.projectPomPath;
|
||||
} else {
|
||||
const parent: Dependency = <Dependency> node.parent;
|
||||
const parent: Dependency = node.parent;
|
||||
selectedPath = localPomPath(parent.groupId, parent.artifactId, parent.version);
|
||||
}
|
||||
await goToDefinition(selectedPath, node.groupId, node.artifactId);
|
||||
|
|
|
@ -32,6 +32,7 @@ export async function parseRawDependencyDataHandler(project: MavenProject): Prom
|
|||
const prefix: string = "+- ";
|
||||
const [treeNodes, conflictNodes] = await parseTreeNodes(treeContent, eol, indent, prefix, project.pomPath);
|
||||
project.conflictNodes = conflictNodes;
|
||||
project.dependencyNodes = treeNodes;
|
||||
return treeNodes;
|
||||
}
|
||||
|
||||
|
@ -86,7 +87,7 @@ async function parseTreeNodes(treecontent: string, eol: string, indent: string,
|
|||
} else {
|
||||
const level: number = (preIndentCnt - curIndentCnt) / indent.length;
|
||||
for (let i = level; i > 0; i -= 1) {
|
||||
parentNode = <Dependency> parentNode.parent;
|
||||
parentNode = parentNode.parent;
|
||||
}
|
||||
parentNode.addChild(curNode);
|
||||
}
|
||||
|
@ -103,7 +104,7 @@ async function parseTreeNodes(treecontent: string, eol: string, indent: string,
|
|||
// find all parent and set hasConflict upforward
|
||||
let tmpNode = curNode;
|
||||
while (tmpNode.parent !== undefined) {
|
||||
const parent = <Dependency> tmpNode.parent;
|
||||
const parent = tmpNode.parent;
|
||||
if (parent.uri.query !== "hasConflict") {
|
||||
parent.uri = uri.with({query: "hasConflict"});
|
||||
tmpNode = parent;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { Disposable } from "vscode";
|
||||
|
||||
class Queue<T> {
|
||||
export class Queue<T> {
|
||||
private _store: T[] = [];
|
||||
public push(val: T): void {
|
||||
this._store.push(val);
|
||||
|
@ -11,6 +11,12 @@ class Queue<T> {
|
|||
public pop(): T | undefined {
|
||||
return this._store.shift();
|
||||
}
|
||||
public empty(): boolean {
|
||||
if (this._store.length === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class TaskExecutor implements Disposable {
|
||||
|
|
Загрузка…
Ссылка в новой задаче