referenceSearch.ts 6.7 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

A
Alex Dima 已提交
7
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
8
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
E
Erich Gamma 已提交
9
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
10 11 12 13 14 15 16 17
import { TPromise } from 'vs/base/common/winjs.base';
import { IEditorService } from 'vs/platform/editor/common/editor';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
A
Alex Dima 已提交
18
import * as editorCommon from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
19 20 21 22 23 24
import { editorAction, ServicesAccessor, EditorAction, CommonEditorRegistry, commonEditorContribution } from 'vs/editor/common/editorCommonExtensions';
import { Location } from 'vs/editor/common/modes';
import { IPeekViewService, PeekContext, getOuterEditor } from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget';
import { provideReferences } from '../common/referenceSearch';
import { ReferencesController, RequestOptions, ctxReferenceSearchVisible } from './referencesController';
import { ReferencesModel } from './referencesModel';
E
Erich Gamma 已提交
25

A
Alex Dima 已提交
26
import ModeContextKeys = editorCommon.ModeContextKeys;
A
Alex Dima 已提交
27
import EditorContextKeys = editorCommon.EditorContextKeys;
A
Alex Dima 已提交
28

29
const defaultReferenceSearchOptions: RequestOptions = {
30 31 32
	getMetaTitle(model) {
		return model.references.length > 1 && nls.localize('meta.titleReference', " – {0} references", model.references.length);
	}
33 34
};

35
@commonEditorContribution
A
Alex Dima 已提交
36
export class ReferenceController implements editorCommon.IEditorContribution {
E
Erich Gamma 已提交
37

38
	private static ID = 'editor.contrib.referenceController';
E
Erich Gamma 已提交
39

40
	constructor(
J
Johannes Rieken 已提交
41
		editor: editorCommon.ICommonCodeEditor,
42
		@IContextKeyService contextKeyService: IContextKeyService,
43 44
		@optional(IPeekViewService) peekViewService: IPeekViewService
	) {
A
Alex Dima 已提交
45
		if (peekViewService) {
46
			PeekContext.inPeekEditor.bindTo(contextKeyService);
A
Alex Dima 已提交
47 48
		}
	}
E
Erich Gamma 已提交
49

A
Alex Dima 已提交
50 51
	public dispose(): void {
	}
E
Erich Gamma 已提交
52

A
Alex Dima 已提交
53 54
	public getId(): string {
		return ReferenceController.ID;
E
Erich Gamma 已提交
55
	}
A
Alex Dima 已提交
56
}
E
Erich Gamma 已提交
57

A
Alex Dima 已提交
58
@editorAction
A
Alex Dima 已提交
59
export class ReferenceAction extends EditorAction {
A
Alex Dima 已提交
60 61

	constructor() {
62 63 64 65
		super({
			id: 'editor.action.referenceSearch.trigger',
			label: nls.localize('references.action.label', "Find All References"),
			alias: 'Find All References',
66 67 68 69
			precondition: ContextKeyExpr.and(
				ModeContextKeys.hasReferenceProvider,
				PeekContext.notInPeekEditor,
				ModeContextKeys.isInWalkThrough.toNegated()),
70 71 72 73 74 75 76 77 78
			kbOpts: {
				kbExpr: EditorContextKeys.TextFocus,
				primary: KeyMod.Shift | KeyCode.F12
			},
			menuOpts: {
				group: 'navigation',
				order: 1.3
			}
		});
E
Erich Gamma 已提交
79 80
	}

J
Johannes Rieken 已提交
81
	public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
82 83 84 85
		let controller = ReferencesController.get(editor);
		if (!controller) {
			return;
		}
A
Alex Dima 已提交
86 87
		let range = editor.getSelection();
		let model = editor.getModel();
88
		let references = provideReferences(model, range.getStartPosition()).then(references => new ReferencesModel(references));
A
Alex Dima 已提交
89
		controller.toggleWidget(range, references, defaultReferenceSearchOptions);
J
Johannes Rieken 已提交
90 91
	}
}
E
Erich Gamma 已提交
92

J
Johannes Rieken 已提交
93
let findReferencesCommand: ICommandHandler = (accessor: ServicesAccessor, resource: URI, position: editorCommon.IPosition) => {
E
Erich Gamma 已提交
94 95 96 97 98

	if (!(resource instanceof URI)) {
		throw new Error('illegal argument, uri');
	}
	if (!position) {
P
Pouya Kary 已提交
99
		throw new Error('illegal argument, position');
E
Erich Gamma 已提交
100 101 102 103
	}

	return accessor.get(IEditorService).openEditor({ resource }).then(editor => {

A
Alex Dima 已提交
104
		let control = <editorCommon.ICommonCodeEditor>editor.getControl();
E
Erich Gamma 已提交
105 106 107 108
		if (!control || typeof control.getEditorType !== 'function') {
			return;
		}

109 110 111 112 113
		let controller = ReferencesController.get(control);
		if (!controller) {
			return;
		}

114
		let references = provideReferences(control.getModel(), Position.lift(position)).then(references => new ReferencesModel(references));
E
Erich Gamma 已提交
115
		let range = new Range(position.lineNumber, position.column, position.lineNumber, position.column);
116
		return TPromise.as(controller.toggleWidget(range, references, defaultReferenceSearchOptions));
E
Erich Gamma 已提交
117
	});
118
};
E
Erich Gamma 已提交
119

J
Johannes Rieken 已提交
120
let showReferencesCommand: ICommandHandler = (accessor: ServicesAccessor, resource: URI, position: editorCommon.IPosition, references: Location[]) => {
121
	if (!(resource instanceof URI)) {
E
Erich Gamma 已提交
122 123 124
		throw new Error('illegal argument, uri expected');
	}

125
	return accessor.get(IEditorService).openEditor({ resource: resource }).then(editor => {
E
Erich Gamma 已提交
126

A
Alex Dima 已提交
127
		let control = <editorCommon.ICommonCodeEditor>editor.getControl();
E
Erich Gamma 已提交
128 129 130 131
		if (!control || typeof control.getEditorType !== 'function') {
			return;
		}

132 133 134 135
		let controller = ReferencesController.get(control);
		if (!controller) {
			return;
		}
136 137

		return TPromise.as(controller.toggleWidget(
A
Alex Dima 已提交
138
			new Range(position.lineNumber, position.column, position.lineNumber, position.column),
139 140
			TPromise.as(new ReferencesModel(references)),
			defaultReferenceSearchOptions)).then(() => true);
E
Erich Gamma 已提交
141 142 143
	});
};

144

E
Erich Gamma 已提交
145

146
// register commands
147

A
Alex Dima 已提交
148
CommandsRegistry.registerCommand('editor.action.findReferences', findReferencesCommand);
149

A
Alex Dima 已提交
150
CommandsRegistry.registerCommand('editor.action.showReferences', {
E
Erich Gamma 已提交
151
	handler: showReferencesCommand,
152 153
	description: {
		description: 'Show references at a position in a file',
J
Johannes Rieken 已提交
154 155 156 157 158
		args: [
			{ name: 'uri', description: 'The text document in which to show references', constraint: URI },
			{ name: 'position', description: 'The position at which to show', constraint: Position.isIPosition },
			{ name: 'locations', description: 'An array of locations.', constraint: Array },
		]
159
	}
E
Erich Gamma 已提交
160
});
161 162

function closeActiveReferenceSearch(accessor, args) {
A
Alex Dima 已提交
163
	var outerEditor = getOuterEditor(accessor, args);
164 165
	if (!outerEditor) {
		return;
E
Erich Gamma 已提交
166
	}
167 168 169 170 171 172 173

	let controller = ReferencesController.get(outerEditor);
	if (!controller) {
		return;
	}

	controller.closeWidget();
174 175
}

A
Alex Dima 已提交
176
KeybindingsRegistry.registerCommandAndKeybindingRule({
177 178 179 180
	id: 'closeReferenceSearch',
	weight: CommonEditorRegistry.commandWeight(50),
	primary: KeyCode.Escape,
	secondary: [KeyMod.Shift | KeyCode.Escape],
A
Alex Dima 已提交
181
	when: ContextKeyExpr.and(ctxReferenceSearchVisible, ContextKeyExpr.not('config.editor.stablePeek')),
182
	handler: closeActiveReferenceSearch
E
Erich Gamma 已提交
183
});
184

A
Alex Dima 已提交
185
KeybindingsRegistry.registerCommandAndKeybindingRule({
186 187 188 189
	id: 'closeReferenceSearchEditor',
	weight: CommonEditorRegistry.commandWeight(-101),
	primary: KeyCode.Escape,
	secondary: [KeyMod.Shift | KeyCode.Escape],
A
Alex Dima 已提交
190
	when: ContextKeyExpr.and(PeekContext.inPeekEditor, ContextKeyExpr.not('config.editor.stablePeek')),
191
	handler: closeActiveReferenceSearch
E
Erich Gamma 已提交
192
});