mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 17:31:43 +00:00
Add Squirrel to the new ref panel (#33638)
This commit is contained in:
parent
782c819e0d
commit
1d6787f8cf
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
},
|
||||
})
|
||||
|
||||
@ -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",
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@ -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"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user