This commit is contained in:
yanzh 2017-11-23 12:26:49 +08:00 коммит произвёл Yan Zhang
Родитель 3954212c0b
Коммит 6397e6f938
9 изменённых файлов: 98 добавлений и 138 удалений

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

@ -221,7 +221,7 @@
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"tslint": "tslint -t verbose src/**/*.ts",
"tslint": "tslint -t verbose src/*.ts",
"watch": "tsc -watch -p ./",
"postinstall": "node ./node_modules/vscode/bin/install",
"test": "npm run compile && node ./node_modules/vscode/bin/test"

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

@ -1,13 +1,13 @@
'use strict';
"use strict";
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import * as path from "path";
import { exec, execSync, spawn } from "child_process";
import * as fs from "fs";
import { MavenProjectsTreeDataProvider } from './mavenProjectsTreeDataProvider';
import { Utils } from './utils';
import { MavenProjectTreeItem } from './mavenProjectTreeItem';
import { execSync, exec, spawn } from 'child_process';
import * as path from "path";
import * as vscode from "vscode";
import { MavenProjectsTreeDataProvider } from "./mavenProjectsTreeDataProvider";
import { MavenProjectTreeItem } from "./mavenProjectTreeItem";
import { Utils } from "./utils";
const ENTRY_NEW_GOALS: string = "New ...";
const ENTRY_OPEN_HIST: string = "View all historical commands";
@ -15,37 +15,34 @@ const ENTRY_OPEN_HIST: string = "View all historical commands";
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "vscode-maven" is now active!');
const mavenProjectsTreeDataProvider = new MavenProjectsTreeDataProvider(context);
vscode.window.registerTreeDataProvider("mavenProjects", mavenProjectsTreeDataProvider);
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let commandMavenProjectsRefresh = vscode.commands.registerCommand('mavenProjects.refresh', () => {
const commandMavenProjectsRefresh = vscode.commands.registerCommand("mavenProjects.refresh", () => {
mavenProjectsTreeDataProvider.refreshTree();
});
let commandMavenGoalExecute = vscode.commands.registerCommand('mavenGoal.exec', (goalItem) => {
const commandMavenGoalExecute = vscode.commands.registerCommand("mavenGoal.exec", (goalItem) => {
const item = goalItem as MavenProjectTreeItem;
Utils.runInTerminal(`mvn ${item.label} -f "${item.pomXmlFilePath}"`, true, `Maven-${item.params.projectName}`);
});
let commandMavenProjectEffectivePom = vscode.commands.registerCommand('mavenProject.effectivePom', (item) => {
const commandMavenProjectEffectivePom = vscode.commands.registerCommand("mavenProject.effectivePom", (item) => {
const pomXmlFilePath = item.fsPath || item.pomXmlFilePath;
const filepath = Utils.getEffectivePomOutputPath(pomXmlFilePath);
let p = new Promise((resolve, reject) => {
const p = new Promise((resolve, reject) => {
exec(`mvn help:effective-pom -f "${pomXmlFilePath}" -Doutput="${filepath}"`, (error, stdout, stderr) => {
if (error || stderr) {
console.error(error);
console.error(stderr);
return resolve(false);
}
resolve(true);
});
}).then(ret => {
}).then((ret) => {
if (ret && fs.existsSync(filepath)) {
const pomxml = fs.readFileSync(filepath).toString();
vscode.workspace.openTextDocument({ language: 'xml', content: pomxml }).then(document => {
vscode.workspace.openTextDocument({ language: "xml", content: pomxml }).then((document) => {
vscode.window.showTextDocument(document);
});
} else {
@ -55,61 +52,63 @@ export function activate(context: vscode.ExtensionContext) {
vscode.window.setStatusBarMessage("Generating effective pom ... ", p);
});
let commandMavenProjectOpenPom = vscode.commands.registerCommand('mavenProject.openPom', (projectItem) => {
const commandMavenProjectOpenPom = vscode.commands.registerCommand("mavenProject.openPom", (projectItem) => {
const item = projectItem as MavenProjectTreeItem;
if (fs.existsSync(item.pomXmlFilePath)) {
vscode.window.showTextDocument(vscode.Uri.file(item.pomXmlFilePath), { preview: false });
}
});
let commandMavenCustomGoal = vscode.commands.registerCommand("mavenGoal.custom", (goalItem) => {
const commandMavenCustomGoal = vscode.commands.registerCommand("mavenGoal.custom", (goalItem) => {
const item = goalItem as MavenProjectTreeItem;
const cmdlist: string[] = Utils.loadCmdHistory(item.pomXmlFilePath);
vscode.window.showQuickPick(cmdlist.concat([ENTRY_NEW_GOALS, ENTRY_OPEN_HIST])).then(selected => {
vscode.window.showQuickPick(cmdlist.concat([ENTRY_NEW_GOALS, ENTRY_OPEN_HIST])).then((selected) => {
if (selected) {
if (selected === ENTRY_NEW_GOALS) {
vscode.window.showInputBox().then((cmd) => {
if (cmd && cmd.trim()) {
cmd = cmd.trim();
Utils.saveCmdHistory(item.pomXmlFilePath, Utils.withLRUItemAhead(cmdlist, cmd));
Utils.runInTerminal(`mvn ${cmd} -f "${item.pomXmlFilePath}"`, true, `Maven-${item.params.projectName}`);
Utils.runInTerminal(`mvn ${cmd} -f "${item.pomXmlFilePath}"`, true,
`Maven-${item.params.projectName}`);
}
});
} else if (selected === ENTRY_OPEN_HIST) {
const historicalFilePath = Utils.getCommandHistoryCachePath(item.pomXmlFilePath);
vscode.window.showTextDocument(vscode.Uri.file(historicalFilePath));
}
else {
} else {
Utils.saveCmdHistory(item.pomXmlFilePath, Utils.withLRUItemAhead(cmdlist, selected));
Utils.runInTerminal(`mvn ${selected} -f "${item.pomXmlFilePath}"`, true, `Maven-${item.params.projectName}`);
Utils.runInTerminal(`mvn ${selected} -f "${item.pomXmlFilePath}"`, true,
`Maven-${item.params.projectName}`);
}
}
});
});
let commandMavenArchetypeGenerate = vscode.commands.registerCommand("mavenArchetype.generate", () => {
vscode.window.showWorkspaceFolderPick().then(ret => { console.log(ret); });
const commandMavenArchetypeGenerate = vscode.commands.registerCommand("mavenArchetype.generate", () => {
const archetypeList = Utils.getArchetypeList();
vscode.window.showQuickPick(archetypeList, { matchOnDescription: true }).then(selected => {
vscode.window.showQuickPick(archetypeList, { matchOnDescription: true }).then((selected) => {
if (selected) {
const { artifactId, groupId } = selected;
vscode.window.showQuickPick(selected.versions).then(version => {
vscode.window.showQuickPick(selected.versions).then((version) => {
if (version) {
Utils.runInTerminal(`mvn archetype:generate -DarchetypeArtifactId=${artifactId} -DarchetypeGroupId=${groupId} -DarchetypeVersion=${version}`, true, 'Maven');
const cmd = `mvn archetype:generate -DarchetypeArtifactId=${artifactId} -DarchetypeGroupId=${groupId} -DarchetypeVersion=${version}`;
Utils.runInTerminal(cmd, true, "Maven");
}
});
}
});
});
let commandMavenArchetypeUpdateCache = vscode.commands.registerCommand("mavenArchetype.updateCache", () => {
vscode.window.showInputBox({ value: "http://repo.maven.apache.org/maven2/archetype-catalog.xml" }).then(url => {
const commandMavenArchetypeUpdateCache = vscode.commands.registerCommand("mavenArchetype.updateCache", () => {
const defaultCatalogUrl = "http://repo.maven.apache.org/maven2/archetype-catalog.xml";
vscode.window.showInputBox({ value: defaultCatalogUrl }).then((url) => {
vscode.window.setStatusBarMessage("Updating archetype catalog ... ", Utils.updateArchetypeCache(url));
});
});
['clean', 'validate', 'compile', 'test', 'package', 'verify', 'install', 'site', 'deploy'].forEach(goal => {
let commandMavenGoal = vscode.commands.registerCommand(`mavenGoal.${goal}`, (goalItem) => {
["clean", "validate", "compile", "test", "package", "verify", "install", "site", "deploy"].forEach((goal) => {
const commandMavenGoal = vscode.commands.registerCommand(`mavenGoal.${goal}`, (goalItem) => {
const item = goalItem as MavenProjectTreeItem;
Utils.runInTerminal(`mvn ${goal} -f "${item.pomXmlFilePath}"`, true, `Maven-${item.params.projectName}`);
});
@ -124,6 +123,6 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(commandMavenArchetypeUpdateCache);
}
// this method is called when your extension is deactivated
export function deactivate() {
}
// this method is called when your extension is deactivated
}

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

@ -1,11 +1,11 @@
import * as vscode from "vscode";
import { QuickPickItem } from "vscode";
export class MavenArchetype implements QuickPickItem {
label: string;
description: string;
artifactId: string;
groupId: string;
versions: string[];
public label: string;
public description: string;
public artifactId: string;
public groupId: string;
public versions: string[];
constructor(aid: string, gid: string, desc?: string) {
this.artifactId = aid;
this.groupId = gid;
@ -13,4 +13,4 @@ export class MavenArchetype implements QuickPickItem {
this.label = `${gid}:${aid}`;
this.description = desc;
}
}
}

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

@ -4,12 +4,11 @@ import { TreeItemCollapsibleState } from "vscode";
export class MavenProjectTreeItem extends vscode.TreeItem {
public pomXmlFilePath: string;
public params: any;
constructor(label: string, pomXmlFilePath: string, contextValue?: string, params?: object) {
super(label, TreeItemCollapsibleState.Collapsed);
this.pomXmlFilePath = pomXmlFilePath;
this.contextValue = contextValue || 'folder';
this.contextValue = contextValue || "folder";
this.params = params || {};
}
}
}

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

@ -1,7 +1,7 @@
import * as vscode from "vscode";
import * as path from "path";
import { MavenProjectTreeItem } from "./mavenProjectTreeItem";
import * as vscode from "vscode";
import { TreeItem, TreeItemCollapsibleState } from "vscode";
import { MavenProjectTreeItem } from "./mavenProjectTreeItem";
import { Utils } from "./utils";
export class MavenProjectsTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
@ -20,7 +20,7 @@ export class MavenProjectsTreeDataProvider implements vscode.TreeDataProvider<vs
if (element === undefined) {
const ret = [];
if (vscode.workspace.workspaceFolders) {
vscode.workspace.workspaceFolders.forEach(wf => {
vscode.workspace.workspaceFolders.forEach((wf) => {
const basepath = wf.uri.fsPath;
const item = Utils.getProject(basepath, "pom.xml");
if (item) {
@ -30,41 +30,39 @@ export class MavenProjectsTreeDataProvider implements vscode.TreeDataProvider<vs
});
}
return Promise.resolve(ret);
}
else if (element.contextValue === 'mavenProject') {
} else if (element.contextValue === "mavenProject") {
const items = [];
// sub modules
const pomObj = element.params.pom;
if (pomObj.project && pomObj.project.modules && pomObj.project.modules.module) {
const pomModule = pomObj.project.modules.module;
const item = new MavenProjectTreeItem("Modules", element.pomXmlFilePath, "Modules", { ...element.params, modules: Array.isArray(pomModule) ? pomModule : [pomModule] });
const item = new MavenProjectTreeItem("Modules", element.pomXmlFilePath, "Modules",
{ ...element.params, modules: Array.isArray(pomModule) ? pomModule : [pomModule] },
);
item.iconPath = this.context.asAbsolutePath(path.join("resources", "folder.svg"));
items.push(item);
}
// others
['Lifecycle' /*, 'Dependencies' */].forEach(name => {
["Lifecycle" /*, 'Dependencies' */].forEach((name) => {
const item = new MavenProjectTreeItem(name, element.pomXmlFilePath, name, element.params);
item.iconPath = this.context.asAbsolutePath(path.join("resources", "folder.svg"));
items.push(item);
});
return Promise.resolve(items);
}
else if (element.contextValue === 'Modules') {
const items = Array.from(element.params.modules, (mod) => Utils.getProject(path.dirname(element.pomXmlFilePath), `${mod}/pom.xml`)).filter(x => x);
items.forEach(item => item.iconPath = this.context.asAbsolutePath(path.join("resources", "project.svg")));
} else if (element.contextValue === "Modules") {
const items = Array.from(element.params.modules, (mod) => Utils.getProject(path.dirname(element.pomXmlFilePath), `${mod}/pom.xml`)).filter((x) => x);
items.forEach((item) => item.iconPath = this.context.asAbsolutePath(path.join("resources", "project.svg")));
return Promise.resolve(items);
}
else if (element.contextValue === 'Lifecycle') {
} else if (element.contextValue === "Lifecycle") {
const items = [];
['clean', 'validate', 'compile', 'test', 'package', 'verify', 'install', 'site', 'deploy'].forEach(goal => {
const item = new MavenProjectTreeItem(goal, element.pomXmlFilePath, 'goal', element.params);
["clean", "validate", "compile", "test", "package", "verify", "install", "site", "deploy"].forEach((goal) => {
const item = new MavenProjectTreeItem(goal, element.pomXmlFilePath, "goal", element.params);
item.collapsibleState = 0;
item.iconPath = this.context.asAbsolutePath(path.join("resources", "goal.svg"));
items.push(item);
});
return Promise.resolve(items);
}
else if (element.contextValue === 'Dependencies') {
} else if (element.contextValue === "Dependencies") {
const items = [];
// TODO
return Promise.resolve(items);
@ -73,4 +71,4 @@ export class MavenProjectsTreeDataProvider implements vscode.TreeDataProvider<vs
public refreshTree(): void {
this._onDidChangeTreeData.fire();
}
}
}

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

@ -1,22 +0,0 @@
//
// Note: This example test is leveraging the Mocha test framework.
// Please refer to their documentation on https://mochajs.org/ for help.
//
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
import * as myExtension from '../extension';
// Defines a Mocha test suite to group tests of similar kind together
suite("Extension Tests", () => {
// Defines a Mocha unit test
test("Something 1", () => {
assert.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
});

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

@ -1,22 +0,0 @@
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
// host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.
import * as testRunner from 'vscode/lib/testrunner';
// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
useColors: true // colored output from test results
});
module.exports = testRunner;

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

@ -1,19 +1,16 @@
import * as vscode from "vscode";
import { execSync } from 'child_process';
import * as fs from 'fs';
import * as http from 'http';
import * as os from 'os';
import * as md5 from "md5";
import * as path from 'path';
import * as xml2js from 'xml2js';
import { MavenProjectTreeItem } from "./mavenProjectTreeItem";
import { MavenArchetype } from "./mavenArchetype";
import { execSync } from "child_process";
import * as fs from "fs";
import { existsSync } from "fs";
import * as http from "http";
import * as md5 from "md5";
import * as os from "os";
import * as path from "path";
import * as vscode from "vscode";
import * as xml2js from "xml2js";
import { MavenArchetype } from "./mavenArchetype";
import { MavenProjectTreeItem } from "./mavenProjectTreeItem";
export class Utils {
private static terminals: { [id: string]: vscode.Terminal } = {};
public static runInTerminal(command: string, addNewLine: boolean = true, terminal: string = "Maven"): void {
if (this.terminals[terminal] === undefined) {
@ -24,10 +21,10 @@ export class Utils {
}
// unused.
public static getPomXmlFilePaths(): string[] {
const filename: string = 'pom.xml';
const filename: string = "pom.xml";
const ret = [];
const stdout = execSync(`find '${vscode.workspace.rootPath}' -name '${filename}'`);
stdout.toString().split('\n').forEach(f => {
stdout.toString().split("\n").forEach((f) => {
if (f) {
ret.push(f);
}
@ -38,7 +35,7 @@ export class Utils {
public static getProject(basePath: string, pomXmlRelativePath: string): MavenProjectTreeItem {
const pomXmlFilePath = path.resolve(basePath, pomXmlRelativePath);
if (fs.existsSync(pomXmlFilePath)) {
const xml = fs.readFileSync(pomXmlFilePath, 'utf8');
const xml = fs.readFileSync(pomXmlFilePath, "utf8");
let pomObject = null;
xml2js.parseString(xml, { explicitArray: false }, (err, res) => { pomObject = res; });
if (pomObject && pomObject.project) {
@ -52,7 +49,7 @@ export class Utils {
public static withLRUItemAhead<T>(array: T[], LRUItem: T): T[] {
const ret = [];
array.forEach(elem => {
array.forEach((elem) => {
if (elem !== LRUItem) {
ret.push(elem);
}
@ -67,7 +64,7 @@ export class Utils {
if (fs.existsSync(filepath)) {
const content = fs.readFileSync(filepath).toString().trim();
if (content) {
return content.split('\n');
return content.split("\n");
}
}
return [];
@ -76,26 +73,26 @@ export class Utils {
public static saveCmdHistory(pomXmlFilePath: string, cmdlist: string[]): void {
const filepath = this.getCommandHistoryCachePath(pomXmlFilePath);
Utils.mkdirp(path.dirname(filepath));
fs.writeFileSync(filepath, cmdlist.join('\n'));
fs.writeFileSync(filepath, cmdlist.join("\n"));
}
public static getEffectivePomOutputPath(pomXmlFilePath: string): string {
return path.join(os.tmpdir(), "vscode-maven", md5(pomXmlFilePath), 'effective-pom.xml');
return path.join(os.tmpdir(), "vscode-maven", md5(pomXmlFilePath), "effective-pom.xml");
}
public static getCommandHistoryCachePath(pomXmlFilePath: string): string {
return path.join(os.tmpdir(), "vscode-maven", md5(pomXmlFilePath), 'commandHistory.txt');
return path.join(os.tmpdir(), "vscode-maven", md5(pomXmlFilePath), "commandHistory.txt");
}
static getArchetypeList(): MavenArchetype[] {
public static getArchetypeList(): MavenArchetype[] {
const localArchetypeXmlFilePath = this.getLocalArchetypeCatalogFilePath();
if (existsSync(localArchetypeXmlFilePath)) {
const xml = fs.readFileSync(localArchetypeXmlFilePath, 'utf8');
const xml = fs.readFileSync(localArchetypeXmlFilePath, "utf8");
let catalog = null;
xml2js.parseString(xml, { explicitArray: false }, (err, res) => { catalog = res; });
if (catalog && catalog['archetype-catalog'] && catalog['archetype-catalog'].archetypes) {
let dict: { [key: string]: MavenArchetype } = {};
catalog['archetype-catalog'].archetypes.archetype.forEach(archetype => {
if (catalog && catalog["archetype-catalog"] && catalog["archetype-catalog"].archetypes) {
const dict: { [key: string]: MavenArchetype } = {};
catalog["archetype-catalog"].archetypes.archetype.forEach((archetype) => {
const identifier = `${archetype.groupId}:${archetype.artifactId}`;
if (!dict[identifier]) {
dict[identifier] = new MavenArchetype(archetype.artifactId, archetype.groupId, archetype.description);
@ -104,7 +101,7 @@ export class Utils {
dict[identifier].versions.push(archetype.version);
}
});
return Object.keys(dict).map(k => dict[k]);
return Object.keys(dict).map((k) => dict[k]);
}
}
return [];
@ -117,20 +114,22 @@ export class Utils {
const filepath = this.getLocalArchetypeCatalogFilePath();
this.mkdirp(path.dirname(filepath));
const file = fs.createWriteStream(filepath);
let ret = new Promise<void>((resolve, reject) => {
const ret = new Promise<void>((resolve, reject) => {
const request = http.get(url, (response) => {
response.pipe(file);
response.on("end", () => {
resolve();
});
});
request.on("error", e => {
request.on("error", (e) => {
reject();
});
});
return ret;
}
private static terminals: { [id: string]: vscode.Terminal } = {};
private static mkdirp(filepath) {
if (fs.existsSync(filepath)) {
return;
@ -138,4 +137,4 @@ export class Utils {
this.mkdirp(path.dirname(filepath));
fs.mkdirSync(filepath);
}
}
}

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

@ -1,11 +1,20 @@
{
"extends": "tslint:recommended",
"rules": {
"variable-name": [
true,
"ban-keywords",
"check-format",
"allow-pascal-case",
"allow-leading-underscore"
],
"no-unused-expression": true,
"no-duplicate-variable": true,
"curly": true,
"class-name": true,
"semicolon": true,
"triple-equals": true
"triple-equals": true,
"max-line-length": false
},
"defaultSeverity": "warning"
}