Port vscode-xquery to vscode-xml

I'll be consolidating the two extensions into one.
This commit is contained in:
Josh Johnson 2016-01-08 10:44:46 -05:00
parent b259f68d72
commit 8738058d8c
8 changed files with 1290 additions and 4 deletions

View File

@ -0,0 +1,11 @@
{
"comments": {
"lineComment": "//",
"blockComment": ["/*", "*/"]
},
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
]
}

File diff suppressed because one or more lines are too long

View File

@ -27,6 +27,7 @@
}, },
"categories": [ "categories": [
"Languages", "Languages",
"Linters",
"Other" "Other"
], ],
"main": "./src/Extension", "main": "./src/Extension",
@ -75,10 +76,26 @@
"key": "ctrl+shift+alt+x", "key": "ctrl+shift+alt+x",
"command": "xmlTools.evaluateXPath" "command": "xmlTools.evaluateXPath"
} }
] ],
"languages": [
{
"id": "xquery",
"aliases": ["XQuery", "xquery"],
"extensions": [".xq",".xql",".xqm",".xqy",".xquery"],
"configuration": "./languages/xquery/xquery.json"
}
],
"grammars": [
{
"language": "xquery",
"scopeName": "source.xquery",
"path": "./languages/xquery/xquery.tmLanguage"
}
]
}, },
"activationEvents": [ "activationEvents": [
"onLanguage:xml" "onLanguage:xml",
"onLanguage:xquery"
], ],
"devDependencies": { "devDependencies": {
"vscode": "^0.10.7", "vscode": "^0.10.7",
@ -86,7 +103,8 @@
}, },
"dependencies": { "dependencies": {
"xmldom": "DotJoshJohnson/xmldom#2794915", "xmldom": "DotJoshJohnson/xmldom#2794915",
"xpath": "^0.0.9" "xpath": "^0.0.9",
"xqlint": "^0.2.9"
}, },
"scripts": { "scripts": {
"vscode:prepublish": "tsc" "vscode:prepublish": "tsc"

View File

@ -3,11 +3,14 @@
import * as vsc from 'vscode'; import * as vsc from 'vscode';
import { TextEditorCommands } from './Commands'; import { TextEditorCommands } from './Commands';
import { XmlFormattingEditProvider } from './providers/Formatting'; import { XmlFormattingEditProvider } from './providers/Formatting';
import { XQueryLintingFeatureProvider } from './providers/Linting';
import { XQueryCompletionItemProvider } from './providers/Completion';
export var GlobalState: vsc.Memento; export var GlobalState: vsc.Memento;
export var WorkspaceState: vsc.Memento; export var WorkspaceState: vsc.Memento;
const LANG_XML: string = 'xml'; const LANG_XML: string = 'xml';
const LANG_XQUERY: string = 'xquery;'
const MEM_QUERY_HISTORY: string = 'xpathQueryHistory'; const MEM_QUERY_HISTORY: string = 'xpathQueryHistory';
export function activate(ctx: vsc.ExtensionContext) { export function activate(ctx: vsc.ExtensionContext) {
@ -25,7 +28,15 @@ export function activate(ctx: vsc.ExtensionContext) {
// register language feature providers // register language feature providers
ctx.subscriptions.push( ctx.subscriptions.push(
vsc.languages.registerDocumentFormattingEditProvider(LANG_XML, new XmlFormattingEditProvider()), vsc.languages.registerDocumentFormattingEditProvider(LANG_XML, new XmlFormattingEditProvider()),
vsc.languages.registerDocumentRangeFormattingEditProvider(LANG_XML, new XmlFormattingEditProvider()) vsc.languages.registerDocumentRangeFormattingEditProvider(LANG_XML, new XmlFormattingEditProvider()),
vsc.languages.registerCompletionItemProvider(LANG_XQUERY, new XQueryCompletionItemProvider(), ':', '$')
);
// listen to editor events (for linting)
ctx.subscriptions.push(
vsc.window.onDidChangeActiveTextEditor(_handleChangeActiveTextEditor),
vsc.window.onDidChangeTextEditorSelection(_handleChangeTextEditorSelection)
); );
} }
@ -36,3 +47,19 @@ export function deactivate() {
history.splice(0); history.splice(0);
memento.update(MEM_QUERY_HISTORY, history); memento.update(MEM_QUERY_HISTORY, history);
} }
function _handleContextChange(editor: vsc.TextEditor): void {
switch (editor.document.languageId) {
case 'xquery':
XQueryLintingFeatureProvider.provideXQueryDiagnostics(editor);
break;
}
}
function _handleChangeActiveTextEditor(editor: vsc.TextEditor): void {
_handleContextChange(editor);
}
function _handleChangeTextEditorSelection(e: vsc.TextEditorSelectionChangeEvent): void {
_handleContextChange(e.textEditor);
}

View File

@ -0,0 +1,46 @@
'use strict';
import * as vsc from 'vscode';
import { XQueryCompleter, XQueryCompletionItem } from '../services/XQueryCompleter';
export class XQueryCompletionItemProvider implements vsc.CompletionItemProvider {
provideCompletionItems(document: vsc.TextDocument, position: vsc.Position): vsc.CompletionItem[] {
let items: vsc.CompletionItem[] = new Array<vsc.CompletionItem>();
let completer: XQueryCompleter = new XQueryCompleter(document.getText());
let completions: XQueryCompletionItem[] = completer.getCompletions(position.line, position.character);
completions.forEach((completion: XQueryCompletionItem) => {
let item: vsc.CompletionItem = new vsc.CompletionItem(completion.name);
item.insertText = completion.value;
switch (completion.meta) {
// functions (always qualified with a colon)
case 'function':
item.kind = vsc.CompletionItemKind.Function;
let funcStart = (completion.value.indexOf(':') + 1);
let funcEnd = completion.value.indexOf('(');
item.insertText = completion.value.substring(funcStart, funcEnd);
break;
// variables and parameters (always qualified with a dollar sign)
case 'Let binding':
case 'Local variable':
case 'Window variable':
case 'Function parameter':
item.kind = vsc.CompletionItemKind.Variable;
item.insertText = completion.value.substring(1);
break;
// everything else
default: item.kind = vsc.CompletionItemKind.Text;
}
items.push(item);
});
return items;
}
}

34
src/providers/Linting.ts Normal file
View File

@ -0,0 +1,34 @@
'use strict';
import * as vsc from 'vscode';
import { XQueryLinter, XQueryDiagnostic } from '../services/XQueryLinter';
export class XQueryLintingFeatureProvider {
private static _coreDiagnostics: vsc.DiagnosticCollection;
static get coreDiagnostics(): vsc.DiagnosticCollection {
if (!XQueryLintingFeatureProvider._coreDiagnostics) {
XQueryLintingFeatureProvider._coreDiagnostics = vsc.languages.createDiagnosticCollection('XQueryDiagnostics');
}
return XQueryLintingFeatureProvider._coreDiagnostics;
}
static provideXQueryDiagnostics(editor: vsc.TextEditor): void {
let diagnostics: vsc.Diagnostic[] = new Array<vsc.Diagnostic>();
let xqDiagnostics: XQueryDiagnostic[] = XQueryLinter.lint(editor.document.getText());
xqDiagnostics.forEach((xqd: XQueryDiagnostic) => {
let vSeverity: vsc.DiagnosticSeverity = (xqd.severity == 1) ? vsc.DiagnosticSeverity.Warning : vsc.DiagnosticSeverity.Error;
let startPos: vsc.Position = new vsc.Position(xqd.startLine, xqd.startColumn);
let endPos: vsc.Position = new vsc.Position(xqd.endLine, xqd.endColumn);
let range: vsc.Range = new vsc.Range(startPos, endPos);
let diagnostic: vsc.Diagnostic = new vsc.Diagnostic(range, xqd.message, vSeverity);
diagnostics.push(diagnostic);
});
XQueryLintingFeatureProvider.coreDiagnostics.set(editor.document.uri, diagnostics);
}
}

View File

@ -0,0 +1,43 @@
'use strict';
let XQLint = require('xqlint').XQLint;
export class XQueryCompleter {
constructor(script: string) {
this.script = script;
}
private _script: string;
private _linter: any;
get script(): string {
return this._script;
}
set script(value: string) {
this._script = value;
this._linter = new XQLint(this._script);
}
getCompletions(line: number, column: number): XQueryCompletionItem[] {
let items: XQueryCompletionItem[] = new Array<XQueryCompletionItem>();
this._linter.getCompletions({line: line, col: column}).forEach((completion: any) => {
items.push(new XQueryCompletionItem(completion.name, completion.value, completion.meta));
});
return items;
}
}
export class XQueryCompletionItem {
constructor(name: string, value: string, meta: string) {
this.name = name;
this.value = value;
this.meta = meta;
}
name: string;
value: string;
meta: string;
}

View File

@ -0,0 +1,41 @@
'use strict';
let XQLint = require('xqlint').XQLint;
export class XQueryLinter {
static SEVERITY_WARNING: number = 1;
static SEVERITY_ERROR: number = 2;
static lint(text: string): XQueryDiagnostic[] {
let linter = new XQLint(text);
let diagnostics: XQueryDiagnostic[] = new Array<XQueryDiagnostic>();
linter.getErrors().forEach((error: any) => {
diagnostics.push(new XQueryDiagnostic(XQueryLinter.SEVERITY_ERROR, error.message, error.pos.sl, error.pos.sc, error.pos.el, error.pos.ec));
});
linter.getWarnings().forEach((warning: any) => {
diagnostics.push(new XQueryDiagnostic(XQueryLinter.SEVERITY_WARNING, warning.message, warning.pos.sl, warning.pos.sc, warning.pos.el, warning.pos.ec));
});
return diagnostics;
}
}
export class XQueryDiagnostic {
constructor(severity: number, message: string, startLine: number, startColumn: number, endLine: number, endColumn: number) {
this.severity = severity;
this.message = message;
this.startLine = startLine;
this.startColumn = startColumn;
this.endLine = endLine;
this.endColumn = endColumn;
}
severity: number;
message: string;
startLine: number;
startColumn: number;
endLine: number;
endColumn: number;
}