This commit is contained in:
Christof Marti 2017-04-28 21:24:34 -07:00
Родитель 1c0b2551f7
Коммит a407c95d8c
6 изменённых файлов: 66 добавлений и 50 удалений

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

@ -70,11 +70,12 @@
"test": "node ./node_modules/vscode/bin/test"
},
"devDependencies": {
"@types/jmespath": "^0.15.0",
"@types/mocha": "^2.2.32",
"@types/node": "^7.0.13",
"mocha": "^2.3.3",
"tslint": "^5.1.0",
"typescript": "^2.0.3",
"typescript": "^2.3.1",
"vscode": "^1.0.0"
},
"dependencies": {

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

@ -4,8 +4,7 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
# TODO: Find reliable way to locate az
source ~/lib/azure-cli/bin/activate || exit 1
source ${1:-~/lib/azure-cli/bin/activate} || exit 1
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink

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

@ -3,7 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { spawn, ChildProcess } from 'child_process';
import { join } from 'path';
import { join, dirname } from 'path';
import { exec } from './utils';
export type CompletionKind = 'group' | 'command' | 'parameter_name' | 'parameter_value';
@ -33,42 +35,55 @@ interface Response {
export class AzService {
private process: ChildProcess | null;
private process: Promise<ChildProcess> | undefined;
private data = '';
private listeners: { [sequence: number]: ((response: Response) => void); } = {};
private nextSequenceNumber = 1;
constructor() {
this.spawn();
this.getProcess();
}
getCompletions(query: CompletionQuery) {
if (!this.process) {
this.spawn();
}
return new Promise<Completion[]>((resolve, reject) => {
const sequence = this.nextSequenceNumber++;
this.listeners[sequence] = response => {
try {
resolve(response.completions);
} catch (err) {
reject(err);
}
};
if (this.process) {
async getCompletions(query: CompletionQuery): Promise<Completion[]> {
try {
const process = await this.getProcess();
return new Promise<Completion[]>((resolve, reject) => {
const sequence = this.nextSequenceNumber++;
this.listeners[sequence] = response => {
try {
resolve(response.completions);
} catch (err) {
reject(err);
}
};
const request: Request = { sequence, query };
const data = JSON.stringify(request);
this.process.stdin.write(data + '\n', 'utf8');
} else {
resolve([]);
}
process.stdin.write(data + '\n', 'utf8');
});
} catch (err) {
console.error(err);
return [];
}
}
private async getProcess(): Promise<ChildProcess> {
if (this.process) {
return this.process;
}
return this.process = exec('az --version').then(({stdout}) => {
const pythonLocation = (/^Python location '([^']*)'/m.exec(stdout) || [])[1];
return this.spawn(pythonLocation);
}).catch(err => {
this.process = undefined;
throw err;
});
}
private spawn() {
this.process = spawn(join(__dirname, '../../service/az-service'));
this.process.stdout.setEncoding('utf8');
this.process.stdout.on('data', data => {
private spawn(pythonLocation: string) {
const args = pythonLocation ? [join(dirname(pythonLocation), 'activate')] : [];
const process = spawn(join(__dirname, '../../service/az-service'), args);
process.stdout.setEncoding('utf8');
process.stdout.on('data', data => {
this.data += data;
const nl = this.data.indexOf('\n');
if (nl !== -1) {
@ -82,16 +97,17 @@ export class AzService {
}
}
});
this.process.stderr.setEncoding('utf8');
this.process.stderr.on('data', data => {
process.stderr.setEncoding('utf8');
process.stderr.on('data', data => {
console.error(data);
});
this.process.on('error', err => {
process.on('error', err => {
console.error(err);
});
this.process.on('exit', (code, signal) => {
process.on('exit', (code, signal) => {
console.error(`Exit code ${code}, signal ${signal}`);
this.process = null;
this.process = undefined;
});
return process;
}
}

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

@ -2,13 +2,12 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as cp from 'child_process';
import * as jmespath from 'jmespath';
import { ExtensionContext, TextDocument, TextDocumentChangeEvent, Disposable, TextEditor, Selection, languages, commands, Range, ViewColumn, Position, CancellationToken, ProviderResult, CompletionItem, CompletionList, CompletionItemKind, CompletionItemProvider, window, workspace } from 'vscode';
import { AzService, CompletionKind, Arguments } from './azService';
import { exec } from './utils';
export function activate(context: ExtensionContext) {
context.subscriptions.push(languages.registerCompletionItemProvider('sha', new AzCompletionItemProvider(), ' '));
@ -170,19 +169,5 @@ function replaceContent(editor: TextEditor, content: string) {
.then(() => editor.selections = [new Selection(0, 0, 0, 0)]);
}
interface ExecResult {
error: Error;
stdout: string;
stderr: string;
}
function exec(command: string) {
return new Promise<ExecResult>((resolve, reject) => {
cp.exec(command, (error, stdout, stderr) => {
(error || stderr ? reject : resolve)({ error, stdout, stderr });
});
});
}
export function deactivate() {
}

15
src/utils.ts Normal file
Просмотреть файл

@ -0,0 +1,15 @@
import * as cp from 'child_process';
export interface ExecResult {
error: Error;
stdout: string;
stderr: string;
}
export function exec(command: string) {
return new Promise<ExecResult>((resolve, reject) => {
cp.exec(command, (error, stdout, stderr) => {
(error || stderr ? reject : resolve)({ error, stdout, stderr });
});
});
}

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

@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"strictNullChecks": true,
"strict": true,
"noUnusedLocals": true,
"outDir": "out",
"lib": [