atom-languageclient
Version:
Integrate Language Servers with Atom
89 lines (82 loc) • 3.62 kB
text/typescript
import type * as atomIde from "atom-ide-base"
import Convert from "../convert"
import { Point, TextEditor } from "atom"
import { LanguageClientConnection, Location, ServerCapabilities, ReferenceParams } from "../languageclient"
/**
* Public: Adapts the language server definition provider to the Atom IDE UI Definitions package for 'Go To Definition'
* functionality.
*/
export default class FindReferencesAdapter {
/**
* Public: Determine whether this adapter can be used to adapt a language server based on the serverCapabilities
* matrix containing a referencesProvider.
*
* @param serverCapabilities The {ServerCapabilities} of the language server to consider.
* @returns A {Boolean} indicating adapter can adapt the server based on the given serverCapabilities.
*/
public static canAdapt(serverCapabilities: ServerCapabilities): boolean {
return serverCapabilities.referencesProvider === true
}
/**
* Public: Get the references for a specific symbol within the document as represented by the {TextEditor} and {Point}
* within it via the language server.
*
* @param connection A {LanguageClientConnection} to the language server that will be queried for the references.
* @param editor The Atom {TextEditor} containing the text the references should relate to.
* @param point The Atom {Point} containing the point within the text the references should relate to.
* @returns A {Promise} containing a {FindReferencesReturn} with all the references the language server could find.
*/
public async getReferences(
connection: LanguageClientConnection,
editor: TextEditor,
point: Point,
projectRoot: string | null
): Promise<atomIde.FindReferencesReturn | null> {
const locations = await connection.findReferences(FindReferencesAdapter.createReferenceParams(editor, point))
if (locations == null) {
return null
}
const references: atomIde.Reference[] = locations.map(FindReferencesAdapter.locationToReference)
return {
type: "data",
baseUri: projectRoot || "",
referencedSymbolName: FindReferencesAdapter.getReferencedSymbolName(editor, point, references),
references,
}
}
/**
* Public: Create a {ReferenceParams} from a given {TextEditor} for a specific {Point}.
*
* @param editor A {TextEditor} that represents the document.
* @param point A {Point} within the document.
* @returns A {ReferenceParams} built from the given parameters.
*/
public static createReferenceParams(editor: TextEditor, point: Point): ReferenceParams {
return {
textDocument: Convert.editorToTextDocumentIdentifier(editor),
position: Convert.pointToPosition(point),
context: { includeDeclaration: true },
}
}
/**
* Public: Convert a {Location} into a {Reference}.
*
* @param location A {Location} to convert.
* @returns A {Reference} equivalent to the given {Location}.
*/
public static locationToReference(location: Location): atomIde.Reference {
return {
uri: Convert.uriToPath(location.uri),
name: null,
range: Convert.lsRangeToAtomRange(location.range),
}
}
/** Public: Get a symbol name from a {TextEditor} for a specific {Point} in the document. */
public static getReferencedSymbolName(editor: TextEditor, point: Point, references: atomIde.Reference[]): string {
if (references.length === 0) {
return ""
}
const currentReference = references.find((r) => r.range.containsPoint(point)) || references[0]
return editor.getBuffer().getTextInRange(currentReference.range)
}
}