2025-11-14 01:21:48 +00:00
|
|
|
import 'server-only';
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-14 01:21:48 +00:00
|
|
|
import { sew } from "@/actions";
|
2025-11-22 23:33:31 +00:00
|
|
|
import { search } from "@/features/search";
|
2025-05-28 23:08:42 +00:00
|
|
|
import { ServiceError } from "@/lib/serviceError";
|
2025-11-14 01:21:48 +00:00
|
|
|
import { isServiceError } from "@/lib/utils";
|
|
|
|
|
import { withOptionalAuthV2 } from "@/withAuthV2";
|
2025-05-28 23:08:42 +00:00
|
|
|
import { SearchResponse } from "../search/types";
|
2025-11-14 01:21:48 +00:00
|
|
|
import { FindRelatedSymbolsRequest, FindRelatedSymbolsResponse } from "./types";
|
2025-11-22 23:33:31 +00:00
|
|
|
import { QueryIR } from '../search/ir';
|
2025-05-28 23:08:42 +00:00
|
|
|
|
|
|
|
|
// The maximum number of matches to return from the search API.
|
|
|
|
|
const MAX_REFERENCE_COUNT = 1000;
|
|
|
|
|
|
2025-11-14 01:21:48 +00:00
|
|
|
export const findSearchBasedSymbolReferences = async (props: FindRelatedSymbolsRequest): Promise<FindRelatedSymbolsResponse | ServiceError> => sew(() =>
|
|
|
|
|
withOptionalAuthV2(async () => {
|
|
|
|
|
const {
|
|
|
|
|
symbolName,
|
|
|
|
|
language,
|
|
|
|
|
revisionName = "HEAD",
|
|
|
|
|
} = props;
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-22 23:33:31 +00:00
|
|
|
const languageFilter = getExpandedLanguageFilter(language);
|
|
|
|
|
|
|
|
|
|
const query: QueryIR = {
|
|
|
|
|
and: {
|
|
|
|
|
children: [
|
|
|
|
|
{
|
|
|
|
|
regexp: {
|
|
|
|
|
regexp: `\\b${symbolName}\\b`,
|
|
|
|
|
case_sensitive: true,
|
|
|
|
|
file_name: false,
|
|
|
|
|
content: true,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
branch: {
|
|
|
|
|
pattern: revisionName,
|
|
|
|
|
exact: true,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
languageFilter,
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-14 01:21:48 +00:00
|
|
|
const searchResult = await search({
|
2025-11-22 23:33:31 +00:00
|
|
|
queryType: 'ir',
|
2025-11-14 01:21:48 +00:00
|
|
|
query,
|
2025-11-22 23:33:31 +00:00
|
|
|
options: {
|
|
|
|
|
matches: MAX_REFERENCE_COUNT,
|
|
|
|
|
contextLines: 0,
|
|
|
|
|
}
|
2025-11-14 01:21:48 +00:00
|
|
|
});
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-14 01:21:48 +00:00
|
|
|
if (isServiceError(searchResult)) {
|
|
|
|
|
return searchResult;
|
|
|
|
|
}
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-14 01:21:48 +00:00
|
|
|
return parseRelatedSymbolsSearchResponse(searchResult);
|
|
|
|
|
}));
|
2025-05-28 23:08:42 +00:00
|
|
|
|
|
|
|
|
|
2025-11-14 01:21:48 +00:00
|
|
|
export const findSearchBasedSymbolDefinitions = async (props: FindRelatedSymbolsRequest): Promise<FindRelatedSymbolsResponse | ServiceError> => sew(() =>
|
|
|
|
|
withOptionalAuthV2(async () => {
|
2025-11-22 23:33:31 +00:00
|
|
|
const {
|
|
|
|
|
symbolName,
|
|
|
|
|
language,
|
|
|
|
|
revisionName = "HEAD",
|
|
|
|
|
} = props;
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-22 23:33:31 +00:00
|
|
|
const languageFilter = getExpandedLanguageFilter(language);
|
|
|
|
|
|
|
|
|
|
const query: QueryIR = {
|
|
|
|
|
and: {
|
|
|
|
|
children: [
|
|
|
|
|
{
|
|
|
|
|
symbol: {
|
|
|
|
|
expr: {
|
|
|
|
|
regexp: {
|
|
|
|
|
regexp: `\\b${symbolName}\\b`,
|
|
|
|
|
case_sensitive: true,
|
|
|
|
|
file_name: false,
|
|
|
|
|
content: true,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
branch: {
|
|
|
|
|
pattern: revisionName,
|
|
|
|
|
exact: true,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
languageFilter,
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-22 23:33:31 +00:00
|
|
|
const searchResult = await search({
|
|
|
|
|
queryType: 'ir',
|
|
|
|
|
query,
|
|
|
|
|
options: {
|
2025-05-28 23:08:42 +00:00
|
|
|
matches: MAX_REFERENCE_COUNT,
|
|
|
|
|
contextLines: 0,
|
|
|
|
|
}
|
2025-11-22 23:33:31 +00:00
|
|
|
});
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-22 23:33:31 +00:00
|
|
|
if (isServiceError(searchResult)) {
|
|
|
|
|
return searchResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return parseRelatedSymbolsSearchResponse(searchResult);
|
2025-11-14 01:21:48 +00:00
|
|
|
}));
|
2025-05-28 23:08:42 +00:00
|
|
|
|
2025-11-22 23:33:31 +00:00
|
|
|
const parseRelatedSymbolsSearchResponse = (searchResult: SearchResponse): FindRelatedSymbolsResponse => {
|
|
|
|
|
return {
|
2025-05-28 23:08:42 +00:00
|
|
|
stats: {
|
2025-10-08 06:55:36 +00:00
|
|
|
matchCount: searchResult.stats.actualMatchCount,
|
2025-05-28 23:08:42 +00:00
|
|
|
},
|
2025-11-22 23:33:31 +00:00
|
|
|
files: searchResult.files.flatMap((file) => {
|
2025-05-28 23:08:42 +00:00
|
|
|
const chunks = file.chunks;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
fileName: file.fileName.text,
|
|
|
|
|
repository: file.repository,
|
|
|
|
|
repositoryId: file.repositoryId,
|
|
|
|
|
webUrl: file.webUrl,
|
|
|
|
|
language: file.language,
|
|
|
|
|
matches: chunks.flatMap((chunk) => {
|
|
|
|
|
return chunk.matchRanges.map((range) => ({
|
|
|
|
|
lineContent: chunk.content,
|
|
|
|
|
range: range,
|
|
|
|
|
}))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}).filter((file) => file.matches.length > 0),
|
|
|
|
|
repositoryInfo: searchResult.repositoryInfo
|
2025-11-22 23:33:31 +00:00
|
|
|
};
|
2025-05-28 23:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expands the language filter to include all variants of the language.
|
2025-11-22 23:33:31 +00:00
|
|
|
const getExpandedLanguageFilter = (language: string): QueryIR => {
|
2025-05-28 23:08:42 +00:00
|
|
|
switch (language) {
|
|
|
|
|
case "TypeScript":
|
|
|
|
|
case "JavaScript":
|
|
|
|
|
case "JSX":
|
|
|
|
|
case "TSX":
|
2025-11-22 23:33:31 +00:00
|
|
|
return {
|
|
|
|
|
or: {
|
|
|
|
|
children: [
|
|
|
|
|
{
|
|
|
|
|
language: {
|
|
|
|
|
language: "TypeScript",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
language: {
|
|
|
|
|
language: "JavaScript",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
language: {
|
|
|
|
|
language: "JSX",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
language: {
|
|
|
|
|
language: "TSX",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
}
|
2025-05-28 23:08:42 +00:00
|
|
|
default:
|
2025-11-22 23:33:31 +00:00
|
|
|
return {
|
|
|
|
|
language: {
|
|
|
|
|
language: language,
|
|
|
|
|
},
|
|
|
|
|
}
|
2025-05-28 23:08:42 +00:00
|
|
|
}
|
|
|
|
|
}
|