Add Squirrel to the new ref panel (#33638)

This commit is contained in:
Chris Wendt 2022-04-14 22:12:08 -06:00 committed by GitHub
parent 782c819e0d
commit 1d6787f8cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 219 additions and 4 deletions

View File

@ -239,6 +239,18 @@ export const CODE_INTEL_SEARCH_QUERY = gql`
}
`
export const LOCAL_CODE_INTEL_QUERY = gql`
query LocalCodeIntel($repository: String!, $commit: String!, $path: String!) {
repository(name: $repository) {
commit(rev: $commit) {
blob(path: $path) {
localCodeIntel
}
}
}
}
`
export const RESOLVE_REPO_REVISION_BLOB_QUERY = gql`
fragment RepoRevisionBlobFields on Repository {
id

View File

@ -44,11 +44,13 @@ export const buildSearchBasedLocation = (node: Result): Location => ({
commitID: node.rev,
content: node.content,
url: node.url,
lines: node.content.split(/\r?\n/),
lines: split(node.content),
precise: false,
range: node.range,
})
export const split = (content: string): string[] => content.split(/\r?\n/)
export const buildPreciseLocation = (node: LocationFields): Location => {
const location: Location = {
content: node.resource.content,

View File

@ -161,6 +161,10 @@ export const useCodeIntel = ({
path: variables.path,
filter: variables.filter ?? undefined,
searchToken,
position: {
line: variables.line,
character: variables.character,
},
fileContent,
spec,
isFork,

View File

@ -1,16 +1,20 @@
import { useCallback, useState } from 'react'
import { flatten } from 'lodash'
import stringify from 'fast-json-stable-stringify'
import { flatten, sortBy } from 'lodash'
import LRU from 'lru-cache'
import { createAggregateError, ErrorLike } from '@sourcegraph/common'
import { Range as ExtensionRange, Position as ExtensionPosition } from '@sourcegraph/extension-api-types'
import { getDocumentNode } from '@sourcegraph/http-client'
import { toPrettyBlobURL } from '@sourcegraph/shared/src/util/url'
import { getWebGraphQLClient } from '../backend/graphql'
import { CodeIntelSearchVariables } from '../graphql-operations'
import { LanguageSpec } from './language-specs/languagespec'
import { Location, buildSearchBasedLocation } from './location'
import { CODE_INTEL_SEARCH_QUERY } from './ReferencesPanelQueries'
import { Location, buildSearchBasedLocation, split } from './location'
import { CODE_INTEL_SEARCH_QUERY, LOCAL_CODE_INTEL_QUERY } from './ReferencesPanelQueries'
import {
definitionQuery,
isExternalPrivateSymbol,
@ -38,6 +42,7 @@ interface UseSearchBasedCodeIntelOptions {
commit: string
path: string
position: ExtensionPosition
searchToken: string
fileContent: string
@ -110,6 +115,8 @@ export async function searchBasedReferences({
commit,
searchToken,
path,
position,
fileContent,
spec,
getSetting,
filter,
@ -117,6 +124,29 @@ export async function searchBasedReferences({
const filterReferences = (results: Location[]): Location[] =>
filter ? results.filter(location => location.file.includes(filter)) : results
const symbol = await findSymbol({ repository: repo, commit, path, row: position.line, column: position.character })
if (symbol?.refs) {
return symbol.refs.map(reference => ({
repo,
file: path,
content: fileContent,
commitID: commit,
range: rangeToExtensionRange(reference),
url: toPrettyBlobURL({
filePath: path,
revision: commit,
repoName: repo,
commitID: commit,
position: {
line: reference.row + 1,
character: reference.column + 1,
},
}),
lines: split(fileContent),
precise: false,
}))
}
const queryTerms = referencesQuery({ searchToken, path, fileExts: spec.fileExts })
const queryArguments = {
repo,
@ -158,10 +188,36 @@ export async function searchBasedDefinitions({
searchToken,
fileContent,
path,
position,
spec,
getSetting,
filter,
}: UseSearchBasedCodeIntelOptions): Promise<Location[]> {
const symbol = await findSymbol({ repository: repo, commit, path, row: position.line, column: position.character })
if (symbol?.def) {
return [
{
repo,
file: path,
content: fileContent,
commitID: commit,
range: rangeToExtensionRange(symbol.def),
url: toPrettyBlobURL({
filePath: path,
revision: commit,
repoName: repo,
commitID: commit,
position: {
line: symbol.def.row + 1,
character: symbol.def.column + 1,
},
}),
lines: split(fileContent),
precise: false,
},
]
}
const filterDefinitions = (results: Location[]): Location[] => {
const filteredByName = filter ? results.filter(location => location.file.includes(filter)) : results
return spec?.filterDefinitions
@ -284,3 +340,132 @@ async function executeSearchQuery(terms: string[]): Promise<SearchResult[]> {
return result.data.search.results.results.filter(isDefined)
}
const findSymbol = async (
repositoryCommitPathPosition: RepositoryCommitPathPosition
): Promise<LocalSymbol | undefined> => {
const payload = await fetchLocalCodeIntelPayload(repositoryCommitPathPosition)
if (!payload) {
return
}
for (const symbol of payload.symbols) {
if (isInRange(repositoryCommitPathPosition, symbol.def)) {
return symbol
}
for (const reference of symbol.refs ?? []) {
if (isInRange(repositoryCommitPathPosition, reference)) {
return symbol
}
}
}
return undefined
}
const cache = <Arguments extends unknown[], V>(
func: (...args: Arguments) => V,
options: LRU.Options<string, V>
): ((...args: Arguments) => V) => {
const lru = new LRU<string, V>(options)
return (...args) => {
const key = stringify(args)
if (lru.has(key)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return lru.get(key)!
}
const value = func(...args)
lru.set(key, value)
return value
}
}
const fetchLocalCodeIntelPayload = cache(
async (repositoryCommitPath: RepositoryCommitPath): Promise<LocalCodeIntelPayload | undefined> => {
const client = await getWebGraphQLClient()
type LocalCodeIntelResponse = GenericBlobResponse<{ localCodeIntel: string }>
const result = await client.query<LocalCodeIntelResponse, RepositoryCommitPath>({
query: getDocumentNode(LOCAL_CODE_INTEL_QUERY),
variables: repositoryCommitPath,
})
if (result.error) {
throw createAggregateError([result.error])
}
const payloadString = result.data.repository?.commit?.blob?.localCodeIntel
if (!payloadString) {
return undefined
}
const payload = JSON.parse(payloadString) as LocalCodeIntelPayload
for (const symbol of payload.symbols) {
if (symbol.refs) {
symbol.refs = sortBy(symbol.refs, reference => reference.row)
}
}
return payload
},
{ max: 10 }
)
interface RepositoryCommitPath {
repository: string
commit: string
path: string
}
type RepositoryCommitPathPosition = RepositoryCommitPath & Position
interface LocalCodeIntelPayload {
symbols: LocalSymbol[]
}
interface LocalSymbol {
hover?: string
def: LocalRange
refs?: LocalRange[]
}
interface LocalRange {
row: number
column: number
length: number
}
interface Position {
row: number
column: number
}
const isInRange = (position: Position, range: LocalRange): boolean => {
if (position.row !== range.row) {
return false
}
if (position.column < range.column) {
return false
}
if (position.column > range.column + range.length) {
return false
}
return true
}
/** The response envelope for all blob queries. */
interface GenericBlobResponse<R> {
repository: { commit: { blob: R | null } | null } | null
}
const rangeToExtensionRange = (range: LocalRange): ExtensionRange => ({
start: {
line: range.row,
character: range.column,
},
end: {
line: range.row,
character: range.column + range.length,
},
})

View File

@ -192,6 +192,7 @@
"@types/js-yaml": "4.0.3",
"@types/jsdom": "12.2.4",
"@types/lodash": "4.14.167",
"@types/lru-cache": "^7.6.1",
"@types/marked": "4.0.3",
"@types/mime-types": "2.1.0",
"@types/mini-css-extract-plugin": "2.0.1",
@ -418,6 +419,7 @@
"js-yaml": "^4.1.0",
"linguist-languages": "^7.14.0",
"lodash": "^4.17.20",
"lru-cache": "^7.8.0",
"marked": "^4.0.0",
"mdi-react": "^8.1.0",
"minimatch": "^3.0.4",

View File

@ -5547,6 +5547,11 @@
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz#4ab7c9ddfc92ec4a887886483bc14c79fb380670"
integrity sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==
"@types/lru-cache@^7.6.1":
version "7.6.1"
resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-7.6.1.tgz#99809260ef1e870b8ef2ab3a625784a33cec5ba9"
integrity sha512-69x+Dhrm2aShFkTqUuPgUXbKYwvq4FH/DVeeQH7MBfTjbKjPX51NGLERxVV1vf33N71dzLvXCko4OLqRvsq53Q==
"@types/markdown-to-jsx@^6.11.3":
version "6.11.3"
resolved "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz#cdd1619308fecbc8be7e6a26f3751260249b020e"
@ -17503,6 +17508,11 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
lru-cache@^7.8.0:
version "7.8.0"
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.0.tgz#649aaeb294a56297b5cbc5d70f198dcc5ebe5747"
integrity sha512-AmXqneQZL3KZMIgBpaPTeI6pfwh+xQ2vutMsyqOu1TBdEXFZgpG/80wuJ531w2ZN7TI0/oc8CPxzh/DKQudZqg==
lru-queue@0.1:
version "0.1.0"
resolved "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"