mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add option to exclude library symbols from navTo results (#55605)
This commit is contained in:
1 parent
6cc605fcfe
commit
b5d6aa73d1
16 files changed
+246
-21
No files matched your search
@@ -9936,6 +9936,7 @@ export interface UserPreferences {
|
||||
readonly organizeImportsNumericCollation?: boolean;
|
||||
readonly organizeImportsAccentCollation?: boolean;
|
||||
readonly organizeImportsCaseFirst?: "upper" | "lower" | false;
|
||||
readonly excludeLibrarySymbolsInNavTo?: boolean;
|
||||
}
|
||||
|
||||
/** Represents a bigint literal value without requiring bigint support */
|
||||
|
||||
+18
-7
@@ -314,15 +314,25 @@ export class SessionClient implements LanguageService {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
getNavigateToItems(searchValue: string): NavigateToItem[] {
|
||||
getNavigateToItems(searchValue: string, maxResultCount: number, file: string | undefined, _excludeDtsFiles: boolean | undefined, excludeLibFiles: boolean | undefined): NavigateToItem[] {
|
||||
const args: protocol.NavtoRequestArgs = {
|
||||
searchValue,
|
||||
file: this.host.getScriptFileNames()[0],
|
||||
file,
|
||||
currentFileOnly: !!file,
|
||||
maxResultCount,
|
||||
};
|
||||
const oldPreferences = this.preferences;
|
||||
if (excludeLibFiles) {
|
||||
this.configure({ excludeLibrarySymbolsInNavTo: true });
|
||||
}
|
||||
|
||||
const request = this.processRequest<protocol.NavtoRequest>(protocol.CommandTypes.Navto, args);
|
||||
const response = this.processResponse<protocol.NavtoResponse>(request);
|
||||
|
||||
if (excludeLibFiles) {
|
||||
this.configure(oldPreferences || {});
|
||||
}
|
||||
|
||||
return response.body!.map(entry => ({ // TODO: GH#18217
|
||||
name: entry.name,
|
||||
containerName: entry.containerName || "",
|
||||
@@ -579,14 +589,13 @@ export class SessionClient implements LanguageService {
|
||||
const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences : preferences?.providePrefixAndSuffixTextForRename;
|
||||
const quotePreference = typeof preferences === "boolean" ? undefined : preferences?.quotePreference;
|
||||
if (providePrefixAndSuffixTextForRename !== undefined || quotePreference !== undefined) {
|
||||
const oldPreferences = this.preferences;
|
||||
// User preferences have to be set through the `Configure` command
|
||||
this.configure({ providePrefixAndSuffixTextForRename, quotePreference });
|
||||
// Options argument is not used, so don't pass in options
|
||||
this.getRenameInfo(fileName, position, /*preferences*/ {}, findInStrings, findInComments);
|
||||
// Restore previous user preferences
|
||||
if (this.preferences) {
|
||||
this.configure(this.preferences);
|
||||
}
|
||||
this.configure(oldPreferences || {});
|
||||
}
|
||||
else {
|
||||
this.getRenameInfo(fileName, position, /*preferences*/ {}, findInStrings, findInComments);
|
||||
@@ -812,6 +821,7 @@ export class SessionClient implements LanguageService {
|
||||
kind?: string,
|
||||
includeInteractiveActions?: boolean,
|
||||
): ApplicableRefactorInfo[] {
|
||||
const oldPreferences = this.preferences;
|
||||
if (preferences) { // Temporarily set preferences
|
||||
this.configure(preferences);
|
||||
}
|
||||
@@ -822,7 +832,7 @@ export class SessionClient implements LanguageService {
|
||||
const request = this.processRequest<protocol.GetApplicableRefactorsRequest>(protocol.CommandTypes.GetApplicableRefactors, args);
|
||||
const response = this.processResponse<protocol.GetApplicableRefactorsResponse>(request);
|
||||
if (preferences) { // Restore preferences
|
||||
this.configure(this.preferences || {});
|
||||
this.configure(oldPreferences || {});
|
||||
}
|
||||
return response.body!; // TODO: GH#18217
|
||||
}
|
||||
@@ -844,6 +854,7 @@ export class SessionClient implements LanguageService {
|
||||
preferences: UserPreferences | undefined,
|
||||
interactiveRefactorArguments?: InteractiveRefactorArguments,
|
||||
): RefactorEditInfo {
|
||||
const oldPreferences = this.preferences;
|
||||
if (preferences) { // Temporarily set preferences
|
||||
this.configure(preferences);
|
||||
}
|
||||
@@ -868,7 +879,7 @@ export class SessionClient implements LanguageService {
|
||||
}
|
||||
|
||||
if (preferences) { // Restore preferences
|
||||
this.configure(this.preferences || {});
|
||||
this.configure(oldPreferences || {});
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -3765,9 +3765,9 @@ export class TestState {
|
||||
}
|
||||
|
||||
public verifyNavigateTo(options: readonly FourSlashInterface.VerifyNavigateToOptions[]): void {
|
||||
for (const { pattern, expected, fileName } of options) {
|
||||
for (const { pattern, expected, fileName, excludeLibFiles } of options) {
|
||||
const file = fileName && this.findFile(fileName).fileName;
|
||||
const items = this.languageService.getNavigateToItems(pattern, /*maxResultCount*/ undefined, file);
|
||||
const items = this.languageService.getNavigateToItems(pattern, /*maxResultCount*/ undefined, file, /*excludeDtsFiles*/ undefined, excludeLibFiles);
|
||||
this.assertObjectsEqual(
|
||||
items,
|
||||
expected.map((e): ts.NavigateToItem => ({
|
||||
|
||||
@@ -1809,6 +1809,7 @@ export interface VerifyNavigateToOptions {
|
||||
readonly pattern: string;
|
||||
readonly fileName?: string;
|
||||
readonly expected: readonly ExpectedNavigateToItem[];
|
||||
readonly excludeLibFiles?: boolean;
|
||||
}
|
||||
|
||||
export interface ExpectedNavigateToItem {
|
||||
|
||||
@@ -3599,6 +3599,11 @@ export interface UserPreferences {
|
||||
* Indicates whether {@link ReferencesResponseItem.lineText} is supported.
|
||||
*/
|
||||
readonly disableLineTextInReferences?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether to exclude standard library and node_modules file symbols from navTo results.
|
||||
*/
|
||||
readonly excludeLibrarySymbolsInNavTo?: boolean;
|
||||
}
|
||||
|
||||
export interface CompilerOptions {
|
||||
|
||||
@@ -2613,6 +2613,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
const { file, project } = this.getFileAndProject(args as protocol.FileRequestArgs);
|
||||
return [{ project, navigateToItems: project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, file) }];
|
||||
}
|
||||
const preferences = this.getHostPreferences();
|
||||
|
||||
const outputs: ProjectNavigateToItems[] = [];
|
||||
|
||||
@@ -2646,7 +2647,13 @@ export class Session<TMessage = string> implements EventSender {
|
||||
|
||||
// Mutates `outputs`
|
||||
function addItemsForProject(project: Project) {
|
||||
const projectItems = project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*fileName*/ undefined, /*excludeDts*/ project.isNonTsProject());
|
||||
const projectItems = project.getLanguageService().getNavigateToItems(
|
||||
searchValue,
|
||||
maxResultCount,
|
||||
/*fileName*/ undefined,
|
||||
/*excludeDts*/ project.isNonTsProject(),
|
||||
/*excludeLibFiles*/ preferences.excludeLibrarySymbolsInNavTo,
|
||||
);
|
||||
const unseenItems = filter(projectItems, item => tryAddSeenItem(item) && !getMappedLocationForProject(documentSpanLocation(item), project));
|
||||
if (unseenItems.length) {
|
||||
outputs.push({ project, navigateToItems: unseenItems });
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
ImportClause,
|
||||
ImportEqualsDeclaration,
|
||||
ImportSpecifier,
|
||||
isInsideNodeModules,
|
||||
isPropertyAccessExpression,
|
||||
isPropertyNameLiteral,
|
||||
NavigateToItem,
|
||||
@@ -37,11 +38,11 @@ interface RawNavigateToItem {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean): NavigateToItem[] {
|
||||
export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean, excludeLibFiles?: boolean): NavigateToItem[] {
|
||||
const patternMatcher = createPatternMatcher(searchValue);
|
||||
if (!patternMatcher) return emptyArray;
|
||||
const rawItems: RawNavigateToItem[] = [];
|
||||
|
||||
const singleCurrentFile = sourceFiles.length === 1 ? sourceFiles[0] : undefined;
|
||||
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
|
||||
for (const sourceFile of sourceFiles) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
@@ -50,8 +51,12 @@ export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shouldExcludeFile(sourceFile, !!excludeLibFiles, singleCurrentFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sourceFile.getNamedDeclarations().forEach((declarations, name) => {
|
||||
getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, sourceFile.fileName, rawItems);
|
||||
getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, sourceFile.fileName, !!excludeLibFiles, singleCurrentFile, rawItems);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -59,7 +64,24 @@ export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker:
|
||||
return (maxResultCount === undefined ? rawItems : rawItems.slice(0, maxResultCount)).map(createNavigateToItem);
|
||||
}
|
||||
|
||||
function getItemsFromNamedDeclaration(patternMatcher: PatternMatcher, name: string, declarations: readonly Declaration[], checker: TypeChecker, fileName: string, rawItems: RawNavigateToItem[]): void {
|
||||
/**
|
||||
* Exclude 'node_modules/' files and standard library files if 'excludeLibFiles' is true.
|
||||
* If we're in current file only mode, we don't exclude the current file, even if it is a library file.
|
||||
*/
|
||||
function shouldExcludeFile(file: SourceFile, excludeLibFiles: boolean, singleCurrentFile: SourceFile | undefined): boolean {
|
||||
return file !== singleCurrentFile && excludeLibFiles && (isInsideNodeModules(file.path) || file.hasNoDefaultLib);
|
||||
}
|
||||
|
||||
function getItemsFromNamedDeclaration(
|
||||
patternMatcher: PatternMatcher,
|
||||
name: string,
|
||||
declarations: readonly Declaration[],
|
||||
checker: TypeChecker,
|
||||
fileName: string,
|
||||
excludeLibFiles: boolean,
|
||||
singleCurrentFile: SourceFile | undefined,
|
||||
rawItems: RawNavigateToItem[],
|
||||
): void {
|
||||
// First do a quick check to see if the name of the declaration matches the
|
||||
// last portion of the (possibly) dotted name they're searching for.
|
||||
const match = patternMatcher.getMatchForLastSegmentOfPattern(name);
|
||||
@@ -68,7 +90,7 @@ function getItemsFromNamedDeclaration(patternMatcher: PatternMatcher, name: stri
|
||||
}
|
||||
|
||||
for (const declaration of declarations) {
|
||||
if (!shouldKeepItem(declaration, checker)) continue;
|
||||
if (!shouldKeepItem(declaration, checker, excludeLibFiles, singleCurrentFile)) continue;
|
||||
|
||||
if (patternMatcher.patternContainsDots) {
|
||||
// If the pattern has dots in it, then also see if the declaration container matches as well.
|
||||
@@ -83,14 +105,20 @@ function getItemsFromNamedDeclaration(patternMatcher: PatternMatcher, name: stri
|
||||
}
|
||||
}
|
||||
|
||||
function shouldKeepItem(declaration: Declaration, checker: TypeChecker): boolean {
|
||||
function shouldKeepItem(
|
||||
declaration: Declaration,
|
||||
checker: TypeChecker,
|
||||
excludeLibFiles: boolean,
|
||||
singleCurrentFile: SourceFile | undefined,
|
||||
): boolean {
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.ImportClause:
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name!)!; // TODO: GH#18217
|
||||
const imported = checker.getAliasedSymbol(importer);
|
||||
return importer.escapedName !== imported.escapedName;
|
||||
return importer.escapedName !== imported.escapedName
|
||||
&& !imported.declarations?.every(d => shouldExcludeFile(d.getSourceFile(), excludeLibFiles, singleCurrentFile));
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2192,10 +2192,10 @@ export function createLanguageService(
|
||||
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry);
|
||||
}
|
||||
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false, excludeLibFiles = false): NavigateToItem[] {
|
||||
synchronizeHostData();
|
||||
const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles();
|
||||
return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles);
|
||||
return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles, excludeLibFiles);
|
||||
}
|
||||
|
||||
function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean) {
|
||||
|
||||
@@ -594,7 +594,7 @@ export interface LanguageService {
|
||||
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined;
|
||||
getFileReferences(fileName: string): ReferenceEntry[];
|
||||
|
||||
getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[];
|
||||
getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean, excludeLibFiles?: boolean): NavigateToItem[];
|
||||
getNavigationBarItems(fileName: string): NavigationBarItem[];
|
||||
getNavigationTree(fileName: string): NavigationTree;
|
||||
|
||||
|
||||
+6
-1
@@ -2897,6 +2897,10 @@ declare namespace ts {
|
||||
* Indicates whether {@link ReferencesResponseItem.lineText} is supported.
|
||||
*/
|
||||
readonly disableLineTextInReferences?: boolean;
|
||||
/**
|
||||
* Indicates whether to exclude standard library and node_modules file symbols from navTo results.
|
||||
*/
|
||||
readonly excludeLibrarySymbolsInNavTo?: boolean;
|
||||
}
|
||||
interface CompilerOptions {
|
||||
allowJs?: boolean;
|
||||
@@ -8640,6 +8644,7 @@ declare namespace ts {
|
||||
readonly organizeImportsNumericCollation?: boolean;
|
||||
readonly organizeImportsAccentCollation?: boolean;
|
||||
readonly organizeImportsCaseFirst?: "upper" | "lower" | false;
|
||||
readonly excludeLibrarySymbolsInNavTo?: boolean;
|
||||
}
|
||||
/** Represents a bigint literal value without requiring bigint support */
|
||||
interface PseudoBigInt {
|
||||
@@ -10396,7 +10401,7 @@ declare namespace ts {
|
||||
findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined;
|
||||
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined;
|
||||
getFileReferences(fileName: string): ReferenceEntry[];
|
||||
getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[];
|
||||
getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean, excludeLibFiles?: boolean): NavigateToItem[];
|
||||
getNavigationBarItems(fileName: string): NavigationBarItem[];
|
||||
getNavigationTree(fileName: string): NavigationTree;
|
||||
prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined;
|
||||
|
||||
@@ -811,6 +811,7 @@ declare namespace FourSlashInterface {
|
||||
readonly pattern: string;
|
||||
readonly fileName?: string;
|
||||
readonly expected: ReadonlyArray<ExpectedNavigateToItem>;
|
||||
readonly excludeLibFiles?: boolean;
|
||||
}
|
||||
interface ExpectedNavigateToItem {
|
||||
readonly name: string;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
// @filename: /index.ts
|
||||
//// import { weirdName as otherName } from "bar";
|
||||
//// const [|weirdName: number = 1|];
|
||||
|
||||
// @filename: /tsconfig.json
|
||||
//// {}
|
||||
|
||||
// @filename: /node_modules/bar/index.d.ts
|
||||
//// export const [|weirdName: number|];
|
||||
|
||||
// @filename: /node_modules/bar/package.json
|
||||
//// {}
|
||||
|
||||
|
||||
const [weird, otherWeird] = test.ranges();
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "weirdName",
|
||||
expected: [{
|
||||
name: "weirdName",
|
||||
kind: "const",
|
||||
kindModifiers: "export,declare",
|
||||
range: otherWeird,
|
||||
matchKind: "exact",
|
||||
},
|
||||
{
|
||||
name: "weirdName",
|
||||
kind: "const",
|
||||
range: weird,
|
||||
matchKind: "exact",
|
||||
}],
|
||||
});
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "weirdName",
|
||||
excludeLibFiles: true,
|
||||
expected: [{
|
||||
name: "weirdName",
|
||||
kind: "const",
|
||||
range: weird,
|
||||
matchKind: "exact",
|
||||
}],
|
||||
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
// @filename: /index.ts
|
||||
//// import { [|someName as weirdName|] } from "bar";
|
||||
|
||||
// @filename: /tsconfig.json
|
||||
//// {}
|
||||
|
||||
// @filename: /node_modules/bar/index.d.ts
|
||||
//// export const someName: number;
|
||||
|
||||
// @filename: /node_modules/bar/package.json
|
||||
//// {}
|
||||
|
||||
|
||||
const [weird] = test.ranges();
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "weirdName",
|
||||
expected: [{
|
||||
name: "weirdName",
|
||||
kind: "alias",
|
||||
range: weird,
|
||||
matchKind: "exact",
|
||||
}],
|
||||
});
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "weirdName",
|
||||
excludeLibFiles: true,
|
||||
expected: [],
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
// @filename: /index.ts
|
||||
//// [|function parseInt(s: string): number {}|]
|
||||
|
||||
const [local] = test.ranges();
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "parseInt",
|
||||
excludeLibFiles: true,
|
||||
expected: [
|
||||
{
|
||||
name: "parseInt",
|
||||
kind: "function",
|
||||
range: local,
|
||||
matchKind: "exact",
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
// @filename: /node_modules/bar/index.d.ts
|
||||
//// import { someOtherName } from "./baz";
|
||||
//// export const [|someName: number|];
|
||||
// @filename: /node_modules/bar/baz.d.ts
|
||||
//// export const someOtherName: string;
|
||||
|
||||
const [some] = test.ranges();
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "some",
|
||||
excludeLibFiles: true,
|
||||
fileName: "/node_modules/bar/index.d.ts",
|
||||
expected: [
|
||||
{
|
||||
name: "someName",
|
||||
kind: "const",
|
||||
kindModifiers: "export,declare",
|
||||
range: some,
|
||||
matchKind: "prefix",
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
/// <reference path="../fourslash.ts"/>
|
||||
|
||||
// @filename: /index.ts
|
||||
//// import { weirdName as otherName } from "bar";
|
||||
//// const [|weirdName: number = 1|];
|
||||
|
||||
// @filename: /tsconfig.json
|
||||
//// {}
|
||||
|
||||
// @filename: /node_modules/bar/index.d.ts
|
||||
//// export const [|weirdName: number|];
|
||||
|
||||
// @filename: /node_modules/bar/package.json
|
||||
//// {}
|
||||
|
||||
|
||||
const [weird, otherWeird] = test.ranges();
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "weirdName",
|
||||
expected: [{
|
||||
name: "weirdName",
|
||||
kind: "const",
|
||||
kindModifiers: "export,declare",
|
||||
range: otherWeird,
|
||||
matchKind: "exact",
|
||||
},
|
||||
{
|
||||
name: "weirdName",
|
||||
kind: "const",
|
||||
range: weird,
|
||||
matchKind: "exact",
|
||||
}],
|
||||
});
|
||||
|
||||
verify.navigateTo({
|
||||
pattern: "weirdName",
|
||||
excludeLibFiles: true,
|
||||
expected: [{
|
||||
name: "weirdName",
|
||||
kind: "const",
|
||||
range: weird,
|
||||
matchKind: "exact",
|
||||
}],
|
||||
});
|
||||
Reference in new issue
Block a user