Merge branch 'vnext'

This commit is contained in:
Johannes Rieken
2016-08-05 14:13:45 +02:00
7 changed files with 50 additions and 42 deletions

View File

@ -11,13 +11,13 @@ It is not intended as a product quality extension.
![Print References](https://raw.githubusercontent.com/Microsoft/vscode-extension-samples/master/contentprovider-sample/preview.gif)
# How it works
# How it works, what it shows?
- The extension implements and registers a [`TextDocumentContentProvider`](http://code.visualstudio.com/docs/extensionAPI/vscode-api#TextDocumentContentProvider) for a particular URI scheme.
- The content provider uses the [`vscode.executeReferenceProvider`](http://code.visualstudio.com/docs/extensionAPI/vscode-api-commands)-API command to delegate searching for references to the language extensions, like TypeScript, vscode-go, or C#
- The generated document initially contains a caption only and incrementally updates as each reference location is resolved.
- The content provider uses the decoration API to highlight matches inside the generated document
- Add links for each result in the virtual document pointing to the reference.
- Add an entry to editor context menu via `package.json`
# How to run locally

View File

@ -12,7 +12,7 @@
"url": "https://github.com/Microsoft/vscode-extension-samples/issues"
},
"engines": {
"vscode": "^1.0.0"
"vscode": "^1.4.0"
},
"categories": [
"Other"
@ -28,6 +28,15 @@
"title": "Show All References"
}
],
"menus": {
"editor/context": [
{
"command": "editor.printReferences",
"when": "editorHasReferenceProvider",
"group": "navigation@1.31"
}
]
},
"languages": [
{
"id": "locations",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -3,15 +3,19 @@
*--------------------------------------------------------*/
'use strict';
import {workspace, window, commands, ExtensionContext} from 'vscode';
import ContentProvider, {encodeLocation} from './contentProvider';
import {workspace, languages, window, commands, ExtensionContext, Disposable} from 'vscode';
import ContentProvider, {encodeLocation} from './provider';
export function activate(context: ExtensionContext) {
const contentProvider = new ContentProvider();
const provider = new ContentProvider();
// register content provider for scheme `references`
const providerRegistration = workspace.registerTextDocumentContentProvider(ContentProvider.scheme, contentProvider);
// register document link provider for scheme `references`
const providerRegistrations = Disposable.from(
workspace.registerTextDocumentContentProvider(ContentProvider.scheme, provider),
languages.registerDocumentLinkProvider({ scheme: ContentProvider.scheme }, provider)
);
// register command that crafts an uri with the `references` scheme,
// open the dynamic document, and shows it in the next editor
@ -21,8 +25,8 @@ export function activate(context: ExtensionContext) {
});
context.subscriptions.push(
contentProvider,
provider,
commandRegistration,
providerRegistration
providerRegistrations
);
}

View File

@ -6,7 +6,7 @@
import * as vscode from 'vscode';
import ReferencesDocument from './referencesDocument';
export default class ContentProvider implements vscode.TextDocumentContentProvider {
export default class Provider implements vscode.TextDocumentContentProvider, vscode.DocumentLinkProvider {
static scheme = 'references';
@ -19,11 +19,7 @@ export default class ContentProvider implements vscode.TextDocumentContentProvid
// Listen to the following events:
// * closeTextDocument - which means we must clear the corresponding model object - `ReferencesDocument`
// * changeActiveEditor - do decorate with references information
this._subscriptions = vscode.Disposable.from(
vscode.workspace.onDidCloseTextDocument(doc => this._documents.delete(doc.uri.toString())),
vscode.window.onDidChangeActiveTextEditor(this._decorateEditor, this)
);
this._subscriptions = vscode.workspace.onDidCloseTextDocument(doc => this._documents.delete(doc.uri.toString()));
}
dispose() {
@ -63,7 +59,7 @@ export default class ContentProvider implements vscode.TextDocumentContentProvid
// sort by locations and shuffle to begin from target resource
let idx = 0;
locations.sort(ContentProvider._compareLocations).find((loc, i) => loc.uri.toString() === target.toString() && (idx = i) && true);
locations.sort(Provider._compareLocations).find((loc, i) => loc.uri.toString() === target.toString() && (idx = i) && true);
locations.push(...locations.splice(0, idx));
// create document and return its early state
@ -73,18 +69,6 @@ export default class ContentProvider implements vscode.TextDocumentContentProvid
});
}
private _decorateEditor(editor: vscode.TextEditor) {
// When an editor opens, check if it shows a `location` document
// and decorate the actual references
if (!editor || !vscode.languages.match('locations', editor.document)) {
return;
}
let doc = this._documents.get(editor.document.uri.toString());
if (doc) {
doc.join().then(() => editor.setDecorations(this._editorDecoration, doc.ranges));
}
}
private static _compareLocations(a: vscode.Location, b: vscode.Location): number {
if (a.uri.toString() < b.uri.toString()) {
return -1;
@ -94,13 +78,23 @@ export default class ContentProvider implements vscode.TextDocumentContentProvid
return a.range.start.compareTo(b.range.start)
}
}
provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentLink[] {
// While building the virtual document we have already created the links.
// Those are composed from the range inside the document and a target uri
// to which they point
const doc = this._documents.get(document.uri.toString());
if (doc) {
return doc.links;
}
}
}
let seq = 0;
export function encodeLocation(uri: vscode.Uri, pos: vscode.Position): vscode.Uri {
const query = JSON.stringify([uri.toString(), pos.line, pos.character]);
return vscode.Uri.parse(`${ContentProvider.scheme}:References.locations?${query}#${seq++}`);
return vscode.Uri.parse(`${Provider.scheme}:References.locations?${query}#${seq++}`);
}
export function decodeLocation(uri: vscode.Uri): [vscode.Uri, vscode.Position] {

View File

@ -12,7 +12,7 @@ export default class ReferencesDocument {
private _locations: vscode.Location[];
private _lines: string[];
private _ranges: vscode.Range[];
private _links: vscode.DocumentLink[];
private _join: Thenable<this>;
constructor(uri: vscode.Uri, locations: vscode.Location[], emitter: vscode.EventEmitter<vscode.Uri>) {
@ -25,7 +25,7 @@ export default class ReferencesDocument {
// Start with printing a header and start resolving
this._lines = [`Found ${this._locations.length} references`];
this._ranges = [];
this._links = [];
this._join = this._populate();
}
@ -33,8 +33,8 @@ export default class ReferencesDocument {
return this._lines.join('\n');
}
get ranges() {
return this._ranges;
get links() {
return this._links;
}
join(): Thenable<this> {
@ -98,7 +98,7 @@ export default class ReferencesDocument {
for (let i = 0; i < ranges.length; i++) {
const {start: {line}} = ranges[i];
this._appendLeading(doc, line, ranges[i - 1]);
this._appendMatch(doc, line, ranges[i]);
this._appendMatch(doc, line, ranges[i], uri);
this._appendTrailing(doc, line, ranges[i + 1]);
}
@ -115,17 +115,18 @@ export default class ReferencesDocument {
}
}
private _appendMatch(doc: vscode.TextDocument, line:number, match: vscode.Range) {
private _appendMatch(doc: vscode.TextDocument, line:number, match: vscode.Range, target: vscode.Uri) {
const text = doc.lineAt(line).text;
const preamble = ` ${line + 1}: `;
// Append line, use new length of lines-array as line number
// for decoration in the document (should really be a link)
// for a link that point to the reference
const len = this._lines.push(preamble + text);
this._ranges.push(new vscode.Range(
len - 1, preamble.length + match.start.character,
len - 1, preamble.length + match.end.character)
);
// Create a document link that will reveal the reference
const linkRange = new vscode.Range(len - 1, preamble.length + match.start.character, len - 1, preamble.length + match.end.character);
const linkTarget = target.with({ fragment: String(1 + match.start.line) });
this._links.push(new vscode.DocumentLink(linkRange, linkTarget));
}
private _appendTrailing(doc: vscode.TextDocument, line: number, next: vscode.Range): void {

View File

@ -9,7 +9,7 @@ The purpose of the extension is to show a preview of the properties in the decla
- Use `Show CSS Properties Preview`
- Position the cursor inside the declaration block of the rule
- The properties are rendered in the preview
- Edit the propertis and the preview is updated
- Edit the properties and the preview is updated
![Navigation](images/preview.gif)