feat: Enhance search ranking with name matching and field extraction improvements
Adds nameMatchBonus scoring to prioritize results where node names exactly or partially match query terms. Implements dedicated field extraction for Java/C# to properly categorize class fields vs variables. Optimizes BM25 search with column weights favoring name matches and increased result fetching before post-processing. Refines stop words list to preserve common programming terms like "get", "find", "list".
This commit is contained in:
@@ -13,7 +13,8 @@ export const csharpExtractor: LanguageExtractor = {
|
||||
typeAliasTypes: [],
|
||||
importTypes: ['using_directive'],
|
||||
callTypes: ['invocation_expression'],
|
||||
variableTypes: ['local_declaration_statement', 'field_declaration'],
|
||||
variableTypes: ['local_declaration_statement'],
|
||||
fieldTypes: ['field_declaration'],
|
||||
nameField: 'name',
|
||||
bodyField: 'body',
|
||||
paramsField: 'parameter_list',
|
||||
|
||||
@@ -13,7 +13,8 @@ export const javaExtractor: LanguageExtractor = {
|
||||
typeAliasTypes: [],
|
||||
importTypes: ['import_declaration'],
|
||||
callTypes: ['method_invocation'],
|
||||
variableTypes: ['local_variable_declaration', 'field_declaration'],
|
||||
variableTypes: ['local_variable_declaration'],
|
||||
fieldTypes: ['field_declaration'],
|
||||
nameField: 'name',
|
||||
bodyField: 'body',
|
||||
paramsField: 'parameters',
|
||||
|
||||
@@ -98,6 +98,8 @@ export interface LanguageExtractor {
|
||||
callTypes: string[];
|
||||
/** Node types that represent variable declarations (const, let, var, etc.) */
|
||||
variableTypes: string[];
|
||||
/** Node types that represent class fields (extracted as 'field' kind inside class bodies) */
|
||||
fieldTypes?: string[];
|
||||
|
||||
// --- Field name mappings ---
|
||||
|
||||
|
||||
@@ -276,6 +276,11 @@ export class TreeSitterExtractor {
|
||||
else if (this.extractor.typeAliasTypes.includes(nodeType)) {
|
||||
this.extractTypeAlias(node);
|
||||
}
|
||||
// Check for class fields (e.g. Java field_declaration, C# field_declaration)
|
||||
else if (this.extractor.fieldTypes?.includes(nodeType) && this.isInsideClassLikeNode()) {
|
||||
this.extractField(node);
|
||||
skipChildren = true;
|
||||
}
|
||||
// Check for variable declarations (const, let, var, etc.)
|
||||
// Only extract top-level variables (not inside functions/methods)
|
||||
else if (this.extractor.variableTypes.includes(nodeType) && !this.isInsideClassLikeNode()) {
|
||||
@@ -656,6 +661,58 @@ export class TreeSitterExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a class field declaration (e.g. Java field_declaration, C# field_declaration).
|
||||
* Extracts each declarator as a 'field' kind node inside the owning class.
|
||||
*/
|
||||
private extractField(node: SyntaxNode): void {
|
||||
if (!this.extractor) return;
|
||||
|
||||
const docstring = getPrecedingDocstring(node, this.source);
|
||||
const visibility = this.extractor.getVisibility?.(node);
|
||||
const isStatic = this.extractor.isStatic?.(node) ?? false;
|
||||
|
||||
// Java field_declaration: "private final String name = value;"
|
||||
// Children include modifiers, type, variable_declarator(s)
|
||||
const declarators = node.namedChildren.filter(
|
||||
c => c.type === 'variable_declarator'
|
||||
);
|
||||
|
||||
if (declarators.length > 0) {
|
||||
// Get field type from the type child
|
||||
const typeNode = node.namedChildren.find(
|
||||
c => c.type !== 'modifiers' && c.type !== 'variable_declarator'
|
||||
&& c.type !== 'marker_annotation' && c.type !== 'annotation'
|
||||
);
|
||||
const typeText = typeNode ? getNodeText(typeNode, this.source) : undefined;
|
||||
|
||||
for (const decl of declarators) {
|
||||
const nameNode = getChildByField(decl, 'name');
|
||||
if (!nameNode) continue;
|
||||
const name = getNodeText(nameNode, this.source);
|
||||
const signature = typeText ? `${typeText} ${name}` : name;
|
||||
this.createNode('field', name, decl, {
|
||||
docstring,
|
||||
signature,
|
||||
visibility,
|
||||
isStatic,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Fallback: try to find an identifier child directly
|
||||
const nameNode = getChildByField(node, 'name')
|
||||
|| node.namedChildren.find(c => c.type === 'identifier');
|
||||
if (nameNode) {
|
||||
const name = getNodeText(nameNode, this.source);
|
||||
this.createNode('field', name, node, {
|
||||
docstring,
|
||||
visibility,
|
||||
isStatic,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a variable declaration (const, let, var, etc.)
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user