Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions x-pack/plugins/code/server/search/document_search_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ function initSearchClient() {
}

const mockSearchResults = [
// 1. The first response is a valid DocumentSearchResult with 1 doc
// 1. The first response is a valid DocumentSearchResult with 2 docs
{
took: 1,
hits: {
total: {
value: 1,
value: 2,
},
hits: [
// File content matching
{
_source: {
repoUri: 'github.com/Microsoft/TypeScript-Node-Starter',
Expand All @@ -45,20 +46,34 @@ const mockSearchResults = [
],
},
},
// File path matching
{
_source: {
repoUri: 'github.com/Microsoft/TypeScript-Node-Starter',
path: 'src/types/string.d.ts',
content:
'no query in content;\nno query in content;\nno query in content;\nno query in content;\nno query in content;\n',
language: 'typescript',
qnames: ['express-flash'],
},
highlight: {
content: [],
},
},
],
},
aggregations: {
repoUri: {
buckets: [
{
'github.com/Microsoft/TypeScript-Node-Starter': 1,
'github.com/Microsoft/TypeScript-Node-Starter': 2,
},
],
},
language: {
buckets: [
{
typescript: 1,
typescript: 2,
},
],
},
Expand Down Expand Up @@ -105,12 +120,12 @@ beforeEach(() => {
initSearchClient();
});

test('Repository search', async () => {
test('Document search', async () => {
// 1. The first response should have 1 result.
const responseWithResult = await docSearchClient.search({ query: 'string', page: 1 });
expect(responseWithResult).toEqual(
expect.objectContaining({
total: 1,
total: 2,
totalPage: 1,
page: 1,
query: 'string',
Expand All @@ -136,15 +151,29 @@ test('Repository search', async () => {
language: 'typescript',
hits: 1,
},
{
uri: 'github.com/Microsoft/TypeScript-Node-Starter',
filePath: 'src/types/string.d.ts',
compositeContent: {
// Content is shorted
content: 'no query in content;\nno query in content;\nno query in content;\n',
// Line mapping data is populated
lineMapping: ['1', '2', '3', '..'],
// Highlight ranges are calculated
ranges: [],
},
language: 'typescript',
hits: 0,
},
],
repoAggregations: [
{
'github.com/Microsoft/TypeScript-Node-Starter': 1,
'github.com/Microsoft/TypeScript-Node-Starter': 2,
},
],
langAggregations: [
{
typescript: 1,
typescript: 2,
},
],
})
Expand All @@ -156,12 +185,12 @@ test('Repository search', async () => {
expect(responseWithEmptyResult.total).toEqual(0);
});

test('Repository suggest', async () => {
test('Document suggest', async () => {
// 1. The first response should have 1 result.
const responseWithResult = await docSearchClient.suggest({ query: 'string', page: 1 });
expect(responseWithResult).toEqual(
expect.objectContaining({
total: 1,
total: 2,
totalPage: 1,
page: 1,
query: 'string',
Expand All @@ -178,6 +207,18 @@ test('Repository suggest', async () => {
language: 'typescript',
hits: 0,
},
{
uri: 'github.com/Microsoft/TypeScript-Node-Starter',
filePath: 'src/types/string.d.ts',
// compositeContent field is intended to leave empty.
compositeContent: {
content: '',
lineMapping: [],
ranges: [],
},
language: 'typescript',
hits: 0,
},
],
})
);
Expand Down
32 changes: 19 additions & 13 deletions x-pack/plugins/code/server/search/document_search_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const MAX_HIT_NUMBER = 5;

export class DocumentSearchClient extends AbstractSearchClient {
private HIGHLIGHT_TAG = '_@_';
private LINE_SEPARATOR = '\n';

constructor(protected readonly client: EsClient, protected readonly log: Logger) {
super(client, log);
Expand Down Expand Up @@ -302,24 +303,29 @@ export class DocumentSearchClient extends AbstractSearchClient {
}

private getSourceContent(hitsContent: SourceHit[], doc: Document) {
const docInLines = doc.content.split(this.LINE_SEPARATOR);
let slicedRanges: LineRange[] = [];
if (hitsContent.length === 0) {
return {
content: '',
lineMapping: [],
ranges: [],
};
// Always add a placeholder range of the first line so that for filepath
// matching search result, we will render some file content.
slicedRanges = [
{
startLine: 0,
endLine: 0,
},
];
} else {
const slicedHighlights = hitsContent.slice(0, MAX_HIT_NUMBER);
slicedRanges = slicedHighlights.map(hit => ({
startLine: hit.range.startLoc.line,
endLine: hit.range.endLoc.line,
}));
}

const slicedHighlights = hitsContent.slice(0, MAX_HIT_NUMBER);
const slicedRanges: LineRange[] = slicedHighlights.map(hit => ({
startLine: hit.range.startLoc.line,
endLine: hit.range.endLoc.line,
}));

const expandedRanges = expandRanges(slicedRanges, HIT_MERGE_LINE_INTERVAL);
const mergedRanges = mergeRanges(expandedRanges);
const lineMapping = new LineMapping();
const result = extractSourceContent(mergedRanges, doc.content.split('\n'), lineMapping);
const result = extractSourceContent(mergedRanges, docInLines, lineMapping);
const ranges: IRange[] = hitsContent
.filter(hit => lineMapping.hasLine(hit.range.startLoc.line))
.map(hit => ({
Expand All @@ -329,7 +335,7 @@ export class DocumentSearchClient extends AbstractSearchClient {
endLineNumber: lineMapping.lineNumber(hit.range.endLoc.line),
}));
return {
content: result.join('\n'),
content: result.join(this.LINE_SEPARATOR),
lineMapping: lineMapping.toStringArray(),
ranges,
};
Expand Down