-
-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(feat) Implement find file references (#1491)
- Loading branch information
Showing
12 changed files
with
270 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
packages/language-server/src/plugins/typescript/features/FindFileReferencesProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { Location } from 'vscode-languageserver'; | ||
import { URI } from 'vscode-uri'; | ||
import { pathToUrl } from '../../../utils'; | ||
import { FileReferencesProvider } from '../../interfaces'; | ||
import { LSAndTSDocResolver } from '../LSAndTSDocResolver'; | ||
import { convertToLocationRange, hasNonZeroRange } from '../utils'; | ||
import { SnapshotFragmentMap } from './utils'; | ||
|
||
export class FindFileReferencesProviderImpl implements FileReferencesProvider { | ||
constructor(private readonly lsAndTsDocResolver: LSAndTSDocResolver) {} | ||
|
||
async fileReferences(uri: string): Promise<Location[] | null> { | ||
const u = URI.parse(uri); | ||
const fileName = u.fsPath; | ||
|
||
const lang = await this.getLSForPath(fileName); | ||
const tsDoc = await this.getSnapshotForPath(fileName); | ||
const fragment = tsDoc.getFragment(); | ||
|
||
const references = lang.getFileReferences(fileName); | ||
|
||
if (!references) { | ||
return null; | ||
} | ||
|
||
const docs = new SnapshotFragmentMap(this.lsAndTsDocResolver); | ||
docs.set(tsDoc.filePath, { fragment, snapshot: tsDoc }); | ||
|
||
const locations = await Promise.all( | ||
references.map(async (ref) => { | ||
const defDoc = await docs.retrieveFragment(ref.fileName); | ||
|
||
return Location.create( | ||
pathToUrl(ref.fileName), | ||
convertToLocationRange(defDoc, ref.textSpan) | ||
); | ||
}) | ||
); | ||
// Some references are in generated code but not wrapped with explicit ignore comments. | ||
// These show up as zero-length ranges, so filter them out. | ||
return locations.filter(hasNonZeroRange); | ||
} | ||
|
||
private async getLSForPath(path: string) { | ||
return this.lsAndTsDocResolver.getLSForPath(path); | ||
} | ||
|
||
private async getSnapshotForPath(path: string) { | ||
return this.lsAndTsDocResolver.getSnapshot(path); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
packages/language-server/test/plugins/typescript/features/FindFileReferencesProvider.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import * as assert from 'assert'; | ||
import * as path from 'path'; | ||
import ts from 'typescript'; | ||
import { Location, Position, Range } from 'vscode-languageserver'; | ||
import { Document, DocumentManager } from '../../../../src/lib/documents'; | ||
import { LSConfigManager } from '../../../../src/ls-config'; | ||
import { FindFileReferencesProviderImpl } from '../../../../src/plugins/typescript/features/FindFileReferencesProvider'; | ||
import { LSAndTSDocResolver } from '../../../../src/plugins/typescript/LSAndTSDocResolver'; | ||
import { pathToUrl } from '../../../../src/utils'; | ||
|
||
const testDir = path.join(__dirname, '..'); | ||
|
||
describe('FindFileReferencesProvider', () => { | ||
function getFullPath(filename: string) { | ||
return path.join(testDir, 'testfiles', filename); | ||
} | ||
function getUri(filename: string) { | ||
const filePath = path.join(testDir, 'testfiles', filename); | ||
return pathToUrl(filePath); | ||
} | ||
|
||
function setup(filename: string) { | ||
const docManager = new DocumentManager( | ||
(textDocument) => new Document(textDocument.uri, textDocument.text) | ||
); | ||
const lsConfigManager = new LSConfigManager(); | ||
const lsAndTsDocResolver = new LSAndTSDocResolver(docManager, [testDir], lsConfigManager); | ||
const provider = new FindFileReferencesProviderImpl(lsAndTsDocResolver); | ||
const document = openDoc(filename); | ||
return { provider, document, openDoc }; | ||
|
||
function openDoc(filename: string) { | ||
const filePath = getFullPath(filename); | ||
const doc = docManager.openDocument(<any>{ | ||
uri: pathToUrl(filePath), | ||
text: ts.sys.readFile(filePath) || '' | ||
}); | ||
return doc; | ||
} | ||
} | ||
|
||
it('finds file references', async () => { | ||
const { provider, document, openDoc } = setup('find-file-references-child.svelte'); | ||
//Make known all the associated files | ||
openDoc('find-file-references-parent.svelte'); | ||
|
||
const results = await provider.fileReferences(document.uri.toString()); | ||
const expectedResults = [ | ||
Location.create( | ||
getUri('find-file-references-parent.svelte'), | ||
Range.create(Position.create(1, 37), Position.create(1, 72)) | ||
) | ||
]; | ||
|
||
assert.deepStrictEqual(results, expectedResults); | ||
}); | ||
}); |
6 changes: 6 additions & 0 deletions
6
packages/language-server/test/plugins/typescript/testfiles/find-file-references-child.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<script> | ||
const findMe = true; | ||
if (findMe) { | ||
findMe; | ||
} | ||
</script> |
10 changes: 10 additions & 0 deletions
10
...ages/language-server/test/plugins/typescript/testfiles/find-file-references-parent.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<script> | ||
import FindFileReferencesChild from "./find-file-references-child.svelte"; | ||
const findMe = true; | ||
if (findMe) { | ||
findMe; | ||
} | ||
</script> | ||
|
||
<FindFileReferencesChild></FindFileReferencesChild> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
packages/svelte-vscode/src/typescript/findFileReferences.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { | ||
commands, | ||
ExtensionContext, | ||
ProgressLocation, | ||
Uri, | ||
window, | ||
workspace, | ||
Position, | ||
Location, | ||
Range | ||
} from 'vscode'; | ||
import { LanguageClient } from 'vscode-languageclient/node'; | ||
import { Location as LSLocation } from 'vscode-languageclient'; | ||
|
||
/** | ||
* adopted from https://github.com/microsoft/vscode/blob/5f3e9c120a4407de3e55465588ce788618526eb0/extensions/typescript-language-features/src/languageFeatures/fileReferences.ts | ||
*/ | ||
export async function addFindFileReferencesListener( | ||
getLS: () => LanguageClient, | ||
context: ExtensionContext | ||
) { | ||
const disposable = commands.registerCommand('svelte.typescript.findAllFileReferences', handler); | ||
|
||
context.subscriptions.push(disposable); | ||
|
||
async function handler(resource?: Uri) { | ||
if (!resource) { | ||
resource = window.activeTextEditor?.document.uri; | ||
} | ||
|
||
if (!resource || resource.scheme !== 'file') { | ||
return; | ||
} | ||
|
||
const document = await workspace.openTextDocument(resource); | ||
|
||
await window.withProgress( | ||
{ | ||
location: ProgressLocation.Window, | ||
title: 'Finding file references' | ||
}, | ||
async (_, token) => { | ||
const lsLocations = await getLS().sendRequest<LSLocation[] | null>( | ||
'$/getFileReferences', | ||
document.uri.toString(), | ||
token | ||
); | ||
|
||
if (!lsLocations) { | ||
return; | ||
} | ||
|
||
const config = workspace.getConfiguration('references'); | ||
const existingSetting = config.inspect<string>('preferredLocation'); | ||
|
||
await config.update('preferredLocation', 'view'); | ||
try { | ||
await commands.executeCommand( | ||
'editor.action.showReferences', | ||
resource, | ||
new Position(0, 0), | ||
lsLocations.map( | ||
(ref) => | ||
new Location( | ||
Uri.parse(ref.uri), | ||
new Range( | ||
ref.range.start.line, | ||
ref.range.start.character, | ||
ref.range.end.line, | ||
ref.range.end.character | ||
) | ||
) | ||
) | ||
); | ||
} finally { | ||
await config.update( | ||
'preferredLocation', | ||
existingSetting?.workspaceFolderValue ?? existingSetting?.workspaceValue | ||
); | ||
} | ||
} | ||
); | ||
} | ||
} |