use std::collections::{BTreeMap, BTreeSet};
use crate::{
code::{
SourceDeclarationMatch, SourceGrepKind, SourceGrepMatch, SourceGrepOutcome,
SourceGrepRequest, simple_source_identifier, source_line_defines_identity,
},
domain::{
CodeQueryKind, CodeRepositoryStatus, CodeRetrievalHit, CodeRetrievalLayer,
CodeRetrievalRequest, StalenessHint,
},
};
use super::source_fallback_imports::{
import_grep_candidate_paths, import_grep_query, local_import_specifier,
quoted_import_specifier, relative_path_import_specifier,
};
use super::source_fallback_surface::{
exact_path_hybrid_source_line_score, hit_allows_source_refresh, hit_source_line_is_better,
hybrid_exact_path_source_fallback, hybrid_source_surface_fallback,
source_type_declaration_line_matches_query,
};
use super::source_surface::hit_has_complete_source_surface;
const MAX_DEFINITION_SOURCE_CANDIDATE_PATHS: usize = 8;
const DYNAMIC_IMPORT_SOURCE_FALLBACK_BONUS: f64 = 1.1;
const HYBRID_EXACT_TYPE_DECLARATION_BONUS: f64 = 6.0;
const REFERENCE_DECLARATION_INTENT_BONUS: f64 = 2.2;
const REFERENCE_SOURCE_DECLARATION_PENALTY: f64 = -1.9;
const GENERATED_FILE_SCORE_MULTIPLIER: f64 = 0.35;
pub(super) struct CodeGrepFallbackPlan {
pub(super) commit: String,
pub(super) query: String,
pub(super) paths: Vec<String>,
pub(super) path_filters: Vec<String>,
pub(super) language_filters: Vec<String>,
pub(super) limit: usize,
pub(super) kind: SourceGrepKind,
pub(super) identity: Option<String>,
pub(super) exclude_generated: bool,
needs_scope_paths: bool,
}
impl CodeGrepFallbackPlan {
pub(super) fn needs_scope_paths(&self) -> bool {
self.needs_scope_paths
}
pub(super) fn with_scope_paths(mut self, scope_paths: Vec<String>) -> Self {
if self.needs_scope_paths {
self.paths = scope_paths;
self.needs_scope_paths = false;
}
self
}
pub(super) fn source_request(&self) -> SourceGrepRequest {
SourceGrepRequest {
query: self.query.clone(),
paths: self.paths.clone(),
path_filters: self.path_filters.clone(),
language_filters: self.language_filters.clone(),
limit: self.limit,
kind: self.kind,
exclude_generated: self.exclude_generated,
}
}
}
pub(super) fn plan_code_grep_fallback(
status: &CodeRepositoryStatus,
request: &CodeRetrievalRequest,
results: &[CodeRetrievalHit],
) -> Option<CodeGrepFallbackPlan> {
let commit = status.last_indexed_commit.clone()?;
if !request.query_kind_filters.is_empty() {
return None;
}
let path_filters = merged_filters(&status.path_filters, &request.repository.path_filters);
let language_filters = query_language_filters(
merged_filters(
&status.language_filters,
&request.repository.language_filters,
),
&request.query_language_filters,
);
match request.code_query_kind {
CodeQueryKind::Definition => {
let identity = definition_identity(&request.query)?;
if results_define_identity(results, &identity)
&& results.iter().any(|hit| {
hit.retrieval_layers
.contains(&CodeRetrievalLayer::Definition)
})
&& results
.iter()
.any(|hit| hit_has_complete_source_surface(hit, &identity))
{
return None;
}
let paths = definition_source_candidate_paths(request, results, &identity);
Some(CodeGrepFallbackPlan {
commit,
query: identity.clone(),
needs_scope_paths: paths.is_empty(),
paths,
path_filters,
language_filters,
limit: request.limit,
kind: SourceGrepKind::Definition,
identity: Some(identity),
exclude_generated: request.exclude_generated,
})
}
CodeQueryKind::References => {
let identity = reference_grep_query(&request.query)?;
if results.iter().any(|hit| {
hit.retrieval_layers
.contains(&CodeRetrievalLayer::Reference)
}) {
return None;
}
let paths = path_filters
.iter()
.filter(|path| exact_file_filter(path))
.map(|path| normalize_filter_path(path).to_owned())
.collect::<Vec<_>>();
let needs_scope_paths = paths.is_empty();
Some(CodeGrepFallbackPlan {
commit,
query: identity,
paths,
path_filters,
language_filters,
limit: request.limit,
kind: SourceGrepKind::References,
identity: None,
exclude_generated: request.exclude_generated,
needs_scope_paths,
})
}
CodeQueryKind::Imports => {
let query = import_grep_query(request, results)?;
let local_relative_query = relative_path_import_specifier(&query);
let paths = if local_relative_query {
Vec::new()
} else {
import_grep_candidate_paths(results, &query)
};
let needs_scope_paths = local_relative_query || paths.is_empty();
Some(CodeGrepFallbackPlan {
commit,
query,
paths,
path_filters,
language_filters,
limit: request.limit,
kind: SourceGrepKind::Imports,
identity: None,
exclude_generated: request.exclude_generated,
needs_scope_paths,
})
}
CodeQueryKind::Hybrid => {
if let Some((query, paths)) = hybrid_exact_path_source_fallback(request, results) {
return Some(CodeGrepFallbackPlan {
commit,
query,
paths,
path_filters,
language_filters,
limit: request.limit,
kind: SourceGrepKind::Hybrid,
identity: None,
exclude_generated: request.exclude_generated,
needs_scope_paths: false,
});
}
if let Some((identity, paths)) = hybrid_source_surface_fallback(request, results) {
return Some(CodeGrepFallbackPlan {
commit,
query: identity,
paths,
path_filters,
language_filters,
limit: request.limit,
kind: SourceGrepKind::Hybrid,
identity: None,
exclude_generated: request.exclude_generated,
needs_scope_paths: false,
});
}
if results.len() >= request.limit {
return None;
}
let identity = source_grep_identity(&request.query)?;
if hybrid_results_cover_identity(results, &identity) {
return None;
}
let paths = path_filters
.iter()
.filter(|path| exact_file_filter(path))
.map(|path| normalize_filter_path(path).to_owned())
.collect::<Vec<_>>();
let needs_scope_paths = paths.is_empty();
Some(CodeGrepFallbackPlan {
commit,
query: identity,
paths,
path_filters,
language_filters,
limit: request.limit.saturating_sub(results.len()).max(1),
kind: SourceGrepKind::Hybrid,
identity: None,
exclude_generated: request.exclude_generated,
needs_scope_paths,
})
}
_ => None,
}
}
pub(super) fn append_code_grep_fallback(
status: &CodeRepositoryStatus,
request: &CodeRetrievalRequest,
results: &mut Vec<CodeRetrievalHit>,
plan: &CodeGrepFallbackPlan,
outcome: SourceGrepOutcome,
) -> Option<String> {
if outcome.matches.is_empty() {
return fallback_diagnostic(plan, outcome.degraded_reason);
}
let score_bounds = ScoreBounds::from_results(results);
let base_fallback_score = grep_score(plan.kind, score_bounds);
let metadata = path_metadata(results);
for matched in outcome.matches {
if !query_field_filters_allow_match(request, &matched.path, &matched.excerpt) {
continue;
}
let fallback_score = generated_adjusted_fallback_score(
source_grep_match_score(request, plan, &matched, score_bounds, base_fallback_score),
matched.is_generated,
);
if let Some(existing) = results.iter_mut().find(|hit| {
hit.path == matched.path
&& hit.line_range.start == matched.line_range.start
&& (hit.excerpt == matched.excerpt
|| (plan.kind == SourceGrepKind::Hybrid && hit_allows_source_refresh(hit)))
}) {
add_code_grep_layers(existing, plan.kind);
if plan.kind == SourceGrepKind::Hybrid
&& hit_allows_source_refresh(existing)
&& hit_source_line_is_better(existing, &matched, &plan.query)
{
existing.excerpt = matched.excerpt.clone();
}
existing.score = existing.score.max(fallback_score);
continue;
}
let mut should_push_nested_match = true;
if plan.kind == SourceGrepKind::Hybrid
&& let Some(existing) = results.iter_mut().find(|hit| {
hit.path == matched.path
&& hit_allows_source_refresh(hit)
&& matched.line_range.start >= hit.line_range.start
&& matched.line_range.end <= hit.line_range.end
})
{
add_code_grep_layers(existing, plan.kind);
if hit_source_line_is_better(existing, &matched, &plan.query) {
existing.excerpt = matched.excerpt.clone();
should_push_nested_match = false;
}
existing.score = existing.score.max(fallback_score);
if matched.line_range.start == existing.line_range.start {
should_push_nested_match = false;
}
}
if !should_push_nested_match {
continue;
}
let path_metadata = metadata.get(&matched.path);
results.push(code_grep_hit(
status,
&matched,
path_metadata,
plan.kind,
fallback_score,
outcome.degraded_reason.clone(),
));
}
dedupe_sort_truncate(results, request.limit);
fallback_diagnostic(plan, outcome.degraded_reason)
}
fn add_code_grep_layers(hit: &mut CodeRetrievalHit, kind: SourceGrepKind) {
if kind == SourceGrepKind::Definition {
add_retrieval_layer(hit, CodeRetrievalLayer::Definition);
}
add_retrieval_layer(hit, CodeRetrievalLayer::Lexical);
add_retrieval_layer(hit, CodeRetrievalLayer::TextFallback);
}
pub(super) fn append_definition_source_fallback(
status: &CodeRepositoryStatus,
request: &CodeRetrievalRequest,
results: &mut Vec<CodeRetrievalHit>,
declarations: Vec<SourceDeclarationMatch>,
) {
if declarations.is_empty() {
return;
}
let best_score = results.first().map_or(0.0, |hit| hit.score);
let metadata = path_metadata(results);
for declaration in declarations {
if !query_field_filters_allow_match(request, &declaration.path, &declaration.excerpt) {
continue;
}
let declaration_score =
generated_adjusted_fallback_score(best_score + 4.0, declaration.is_generated);
if let Some(existing) = results.iter_mut().find(|hit| {
hit.path == declaration.path
&& hit.line_range.start == declaration.line_range.start
&& hit.excerpt == declaration.excerpt
}) {
add_retrieval_layer(existing, CodeRetrievalLayer::Definition);
add_retrieval_layer(existing, CodeRetrievalLayer::Lexical);
add_retrieval_layer(existing, CodeRetrievalLayer::TextFallback);
existing.score = existing.score.max(declaration_score);
continue;
}
let path_metadata = metadata.get(&declaration.path);
results.push(CodeRetrievalHit {
repository_id: status.repository_id.clone(),
scope_id: status.last_indexed_scope_id.clone().unwrap_or_default(),
resolved_commit_sha: status.last_indexed_commit.clone().unwrap_or_default(),
tree_hash: status.tree_hash.clone().unwrap_or_default(),
path: declaration.path,
language_id: path_metadata
.map(|metadata| metadata.language_id.clone())
.unwrap_or_default(),
byte_range: declaration.byte_range,
line_range: declaration.line_range,
symbol_snapshot_id: path_metadata
.and_then(|metadata| metadata.symbol_snapshot_id.clone()),
canonical_symbol_id: path_metadata
.and_then(|metadata| metadata.canonical_symbol_id.clone()),
file_id: path_metadata.and_then(|metadata| metadata.file_id.clone()),
retrieval_layers: vec![
CodeRetrievalLayer::Definition,
CodeRetrievalLayer::Lexical,
CodeRetrievalLayer::TextFallback,
],
index_versions: vec![format!(
"code:{}:{}",
status
.last_indexed_scope_id
.as_deref()
.unwrap_or("unscoped"),
status.tree_hash.as_deref().unwrap_or("unindexed")
)],
stale: status.stale,
staleness_hint: Some(if status.stale {
StalenessHint::Stale {}
} else {
StalenessHint::Fresh
}),
degraded_reason: status.degraded_reason.clone(),
edge_kind: None,
edge_resolution_state: None,
edge_target_hint: None,
edge_confidence_basis_points: None,
edge_confidence_tier: None,
score: declaration_score,
excerpt: declaration.excerpt,
});
}
dedupe_sort_truncate(results, request.limit);
}
fn add_retrieval_layer(hit: &mut CodeRetrievalHit, layer: CodeRetrievalLayer) {
if !hit.retrieval_layers.contains(&layer) {
hit.retrieval_layers.push(layer);
}
}
fn code_grep_hit(
status: &CodeRepositoryStatus,
matched: &SourceGrepMatch,
path_metadata: Option<&HitPathMetadata>,
kind: SourceGrepKind,
score: f64,
degraded_reason: Option<String>,
) -> CodeRetrievalHit {
let mut layers = vec![
CodeRetrievalLayer::Lexical,
CodeRetrievalLayer::TextFallback,
];
if kind == SourceGrepKind::Definition {
layers.insert(0, CodeRetrievalLayer::Definition);
}
CodeRetrievalHit {
repository_id: status.repository_id.clone(),
scope_id: status.last_indexed_scope_id.clone().unwrap_or_default(),
resolved_commit_sha: status.last_indexed_commit.clone().unwrap_or_default(),
tree_hash: status.tree_hash.clone().unwrap_or_default(),
path: matched.path.clone(),
language_id: path_metadata
.map(|metadata| metadata.language_id.clone())
.unwrap_or_else(|| matched.language_id.clone()),
byte_range: matched.byte_range.clone(),
line_range: matched.line_range.clone(),
symbol_snapshot_id: path_metadata.and_then(|metadata| metadata.symbol_snapshot_id.clone()),
canonical_symbol_id: path_metadata
.and_then(|metadata| metadata.canonical_symbol_id.clone()),
file_id: path_metadata.and_then(|metadata| metadata.file_id.clone()),
retrieval_layers: layers,
index_versions: vec![format!(
"code:{}:{}",
status
.last_indexed_scope_id
.as_deref()
.unwrap_or("unscoped"),
status.tree_hash.as_deref().unwrap_or("unindexed")
)],
stale: status.stale,
staleness_hint: Some(if status.stale {
StalenessHint::Stale {}
} else {
StalenessHint::Fresh
}),
degraded_reason: degraded_reason.or_else(|| status.degraded_reason.clone()),
edge_kind: None,
edge_resolution_state: None,
edge_target_hint: None,
edge_confidence_basis_points: None,
edge_confidence_tier: None,
score,
excerpt: matched.excerpt.clone(),
}
}
#[derive(Clone, Copy)]
struct ScoreBounds {
best: Option<f64>,
lowest: Option<f64>,
}
impl ScoreBounds {
fn from_results(results: &[CodeRetrievalHit]) -> Self {
let mut bounds = Self {
best: None,
lowest: None,
};
for hit in results {
bounds.best = Some(bounds.best.map_or(hit.score, |best| best.max(hit.score)));
bounds.lowest = Some(
bounds
.lowest
.map_or(hit.score, |lowest| lowest.min(hit.score)),
);
}
bounds
}
}
fn grep_score(kind: SourceGrepKind, score_bounds: ScoreBounds) -> f64 {
match kind {
SourceGrepKind::Definition => score_bounds.best.unwrap_or(0.0) + 3.5,
SourceGrepKind::References => score_bounds.best.unwrap_or(0.0) + 2.0,
SourceGrepKind::Imports | SourceGrepKind::Hybrid => {
score_bounds.lowest.map(|score| score - 0.25).unwrap_or(1.0)
}
}
}
fn fallback_diagnostic(
plan: &CodeGrepFallbackPlan,
degraded_reason: Option<String>,
) -> Option<String> {
let external_import_fallback =
plan.kind == SourceGrepKind::Imports && !local_import_specifier(&plan.query);
let reason = degraded_reason?;
if external_import_fallback {
Some(format!(
"source fallback for unresolved external import failed: {reason}"
))
} else {
Some(reason)
}
}
fn source_grep_match_score(
request: &CodeRetrievalRequest,
plan: &CodeGrepFallbackPlan,
matched: &SourceGrepMatch,
score_bounds: ScoreBounds,
base_score: f64,
) -> f64 {
if plan.kind == SourceGrepKind::Hybrid
&& plan.paths.iter().any(|path| exact_file_filter(path))
&& source_type_declaration_line_matches_query(&matched.excerpt, &request.query)
{
return score_bounds.best.unwrap_or(base_score) + HYBRID_EXACT_TYPE_DECLARATION_BONUS;
}
if plan.kind == SourceGrepKind::Hybrid {
if let Some(score) = exact_path_hybrid_source_line_score(
request,
plan.paths.as_slice(),
matched,
score_bounds.lowest,
) {
return score;
}
}
let adjustment = match plan.kind {
SourceGrepKind::References => {
reference_source_grep_score_adjustment(&request.query, &plan.query, &matched.excerpt)
}
SourceGrepKind::Imports => {
import_source_grep_score_adjustment(&request.query, &plan.query, &matched.excerpt)
}
SourceGrepKind::Definition | SourceGrepKind::Hybrid => 0.0,
};
(base_score + adjustment).max(0.0)
}
fn generated_adjusted_fallback_score(score: f64, is_generated: bool) -> f64 {
if is_generated {
score * GENERATED_FILE_SCORE_MULTIPLIER
} else {
score
}
}
fn import_source_grep_score_adjustment(query: &str, specifier: &str, excerpt: &str) -> f64 {
let line = excerpt.trim();
if query_prefers_dynamic_import_source(query)
&& relative_path_import_specifier(specifier)
&& !source_line_starts_with_comment(line)
&& line.contains(specifier)
&& (line.contains("import(") || line.contains("import ("))
{
DYNAMIC_IMPORT_SOURCE_FALLBACK_BONUS
} else {
0.0
}
}
fn query_prefers_dynamic_import_source(query: &str) -> bool {
let query = query.trim();
if quoted_import_specifier(query).is_none() {
return false;
}
query.match_indices("import").any(|(index, _)| {
let tail = &query[index + "import".len()..];
let has_call = tail.starts_with('(') || tail.starts_with(" (");
let has_token_boundary = query[..index].chars().last().is_none_or(|character| {
!character.is_ascii_alphanumeric() && character != '_' && character != '.'
});
has_call && has_token_boundary
})
}
fn source_line_starts_with_comment(line: &str) -> bool {
["//", "#", "/*", "*", "--", "<!--"]
.iter()
.any(|prefix| line.starts_with(prefix))
}
fn reference_source_grep_score_adjustment(query: &str, identity: &str, excerpt: &str) -> f64 {
if !simple_source_identifier(identity) {
return 0.0;
}
let line = excerpt.trim();
if line.is_empty() || line.starts_with("//") || line.starts_with('*') {
return 0.0;
}
if source_reference_line_declares_identity(line, identity) {
if reference_query_has_declaration_intent(query) {
REFERENCE_DECLARATION_INTENT_BONUS
} else {
REFERENCE_SOURCE_DECLARATION_PENALTY
}
} else {
0.0
}
}
fn reference_query_has_declaration_intent(query: &str) -> bool {
query
.split(|character: char| !(character.is_ascii_alphanumeric() || character == '_'))
.any(|term| matches!(term, "typedef" | "typealias" | "alias" | "using"))
}
fn source_reference_line_declares_identity(line: &str, identity: &str) -> bool {
if source_line_defines_identity(line, identity) {
return true;
}
source_identifier_ranges(line, identity).any(|(start, end)| {
let before = line.get(..start).unwrap_or_default().trim_end();
let after = line.get(end..).unwrap_or_default().trim_start();
if before.ends_with('.') || before.ends_with("->") || identifier_is_assignment_value(before)
{
return false;
}
if after.starts_with('[') && array_declarator_has_initializer(after) {
return true;
}
declaration_prefix_before_identity(before)
&& before.split_whitespace().last() != Some(identity)
})
}
fn source_identifier_ranges<'a>(
line: &'a str,
identity: &'a str,
) -> impl Iterator<Item = (usize, usize)> + 'a {
line.match_indices(identity).filter_map(|(start, _)| {
let end = start + identity.len();
let has_start_boundary = line.get(..start).is_some_and(|prefix| {
prefix
.chars()
.next_back()
.is_none_or(|character| !source_identifier_char(character))
});
let has_end_boundary = line.get(end..).is_some_and(|suffix| {
suffix
.chars()
.next()
.is_none_or(|character| !source_identifier_char(character))
});
(has_start_boundary && has_end_boundary).then_some((start, end))
})
}
fn declaration_prefix_before_identity(before: &str) -> bool {
let mut tokens = before.split_whitespace();
let Some(first_token) = tokens.next() else {
return false;
};
if statement_prefix_token(first_token) {
return false;
}
let token_count = before.split_whitespace().count();
token_count >= 1
&& before
.chars()
.all(|character| !matches!(character, '=' | '+' | '-' | '*' | '/' | '%' | '?'))
}
fn statement_prefix_token(token: &str) -> bool {
matches!(
token.trim_matches(|character: char| !source_identifier_char(character)),
"return"
| "if"
| "for"
| "while"
| "switch"
| "case"
| "sizeof"
| "typeof"
| "alignof"
| "offsetof"
| "throw"
| "yield"
| "await"
)
}
fn array_declarator_has_initializer(after: &str) -> bool {
let Some(equals_index) = after.find('=') else {
return false;
};
!after
.get(..equals_index)
.is_some_and(|prefix| prefix.contains(')'))
}
fn identifier_is_assignment_value(before: &str) -> bool {
before
.chars()
.rev()
.find(|character| !character.is_whitespace())
.is_some_and(|character| character == '=')
}
fn source_identifier_char(character: char) -> bool {
character.is_ascii_alphanumeric() || character == '_'
}
fn definition_source_candidate_paths(
request: &CodeRetrievalRequest,
results: &[CodeRetrievalHit],
identity: &str,
) -> Vec<String> {
let mut paths = Vec::new();
for hit in results {
if hit_mentions_identity(hit, identity) {
push_candidate_path(&mut paths, &hit.path);
}
}
for path in &request.repository.path_filters {
if exact_file_filter(path) {
push_candidate_path(&mut paths, path);
}
}
paths.truncate(MAX_DEFINITION_SOURCE_CANDIDATE_PATHS);
paths
}
fn hit_mentions_identity(hit: &CodeRetrievalHit, identity: &str) -> bool {
hit.excerpt.contains(identity)
|| hit
.canonical_symbol_id
.as_deref()
.is_some_and(|symbol_id| symbol_id.contains(identity))
}
fn hybrid_results_cover_identity(results: &[CodeRetrievalHit], identity: &str) -> bool {
results.iter().any(|hit| {
hit.retrieval_layers.iter().any(|layer| {
matches!(
layer,
CodeRetrievalLayer::Symbol | CodeRetrievalLayer::Definition
)
}) && (hit
.canonical_symbol_id
.as_deref()
.is_some_and(|symbol_id| canonical_symbol_leaf_matches(symbol_id, identity))
|| hit
.excerpt
.lines()
.any(|line| source_identifier_ranges(line, identity).next().is_some()))
})
}
fn canonical_symbol_leaf_matches(canonical_symbol_id: &str, identity: &str) -> bool {
canonical_symbol_id
.rsplit(|character: char| !source_identifier_char(character))
.find(|term| !term.is_empty())
.is_some_and(|leaf| leaf == identity)
}
pub(super) fn push_candidate_path(paths: &mut Vec<String>, path: &str) {
let normalized = normalize_filter_path(path);
if !normalized.is_empty() && !paths.iter().any(|existing| existing == normalized) {
paths.push(normalized.to_owned());
}
}
fn exact_file_filter(path: &str) -> bool {
let path = normalize_filter_path(path);
!path.is_empty()
&& path
.rsplit('/')
.next()
.is_some_and(|name| name.contains('.'))
&& !path.ends_with('/')
}
fn normalize_filter_path(path: &str) -> &str {
let mut path = path.trim_end_matches(['/', '\\']);
while let Some(stripped) = path.strip_prefix("./") {
path = stripped;
}
path
}
fn results_define_identity(results: &[CodeRetrievalHit], identity: &str) -> bool {
results.iter().any(|hit| {
hit.excerpt
.lines()
.map(str::trim)
.any(|line| source_line_defines_identity(line, identity))
})
}
pub(super) fn definition_identity(query: &str) -> Option<String> {
let mut identity = None;
for raw_token in query.split_whitespace().map(str::trim) {
if raw_token.contains('/') || raw_token.contains('\\') {
continue;
}
let terms = raw_token
.split(|character: char| !(character.is_ascii_alphanumeric() || character == '_'))
.filter(|term| !term.is_empty())
.collect::<Vec<_>>();
if let Some(term) = terms.last().filter(|term| simple_source_identifier(term)) {
identity = Some((*term).to_owned());
}
}
identity
}
fn source_grep_identity(query: &str) -> Option<String> {
let identity = definition_identity(query)?;
(query.split_whitespace().count() == 1).then_some(identity)
}
fn reference_grep_query(query: &str) -> Option<String> {
source_grep_identity(query).or_else(|| leading_source_identifier(query))
}
fn leading_source_identifier(query: &str) -> Option<String> {
for raw_token in query.split_whitespace().map(str::trim) {
if raw_token.contains('/') || raw_token.contains('\\') {
continue;
}
let token = raw_token.trim_matches(|character: char| {
!(character.is_ascii_alphanumeric()
|| character == '_'
|| character == '.'
|| character == ':')
});
if token.is_empty() {
continue;
}
if (token.contains('.') || token.contains("::"))
&& token
.split(|character: char| !(character.is_ascii_alphanumeric() || character == '_'))
.filter(|term| simple_source_identifier(term))
.count()
>= 2
{
return Some(token.to_owned());
}
if let Some(term) = token
.split(|character: char| !(character.is_ascii_alphanumeric() || character == '_'))
.find(|term| term.len() >= 3 && simple_source_identifier(term))
{
return Some(term.to_owned());
}
}
None
}
fn merged_filters(left: &[String], right: &[String]) -> Vec<String> {
let mut merged = Vec::new();
for value in left.iter().chain(right.iter()) {
if !merged.contains(value) {
merged.push(value.clone());
}
}
merged
}
fn query_language_filters(base_filters: Vec<String>, query_filters: &[String]) -> Vec<String> {
const NO_MATCHING_LANGUAGE_FILTER: &str = "__relay_no_matching_language__";
const C_CPP_HEADER_LANGUAGE_FILTER: &str = "__relay_c_cpp_header_only__";
if query_filters.is_empty() {
return base_filters;
}
if base_filters.is_empty() {
return query_filters.to_vec();
}
let mut intersection = Vec::new();
for query_filter in query_filters {
for base_filter in &base_filters {
if base_filter == query_filter && !intersection.contains(query_filter) {
intersection.push(query_filter.clone());
} else if c_cpp_header_language_overlap(base_filter, query_filter)
&& !intersection
.iter()
.any(|filter| filter == C_CPP_HEADER_LANGUAGE_FILTER)
{
intersection.push(C_CPP_HEADER_LANGUAGE_FILTER.to_owned());
}
}
}
let mut intersection = merged_filters(&[], &intersection);
if intersection.is_empty() {
intersection.push(NO_MATCHING_LANGUAGE_FILTER.to_owned());
}
intersection
}
fn c_cpp_header_language_overlap(base_filter: &str, query_filter: &str) -> bool {
matches!((base_filter, query_filter), ("c", "cpp") | ("cpp", "c"))
}
fn query_field_filters_allow_match(
request: &CodeRetrievalRequest,
path: &str,
excerpt: &str,
) -> bool {
request.query_kind_filters.is_empty()
&& filters_match_text(&request.query_path_substrings, path)
&& source_fallback_name_filters_match(request, excerpt)
}
fn source_fallback_name_filters_match(request: &CodeRetrievalRequest, excerpt: &str) -> bool {
request.query_name_substrings.is_empty()
|| request.query_name_substrings.iter().any(|filter| {
text_matches_filter(&request.query, filter) || text_matches_filter(excerpt, filter)
})
}
fn filters_match_text(filters: &[String], text: &str) -> bool {
filters.is_empty()
|| filters
.iter()
.any(|filter| text_matches_filter(text, filter))
}
fn text_matches_filter(text: &str, filter: &str) -> bool {
text.to_ascii_lowercase()
.contains(&filter.to_ascii_lowercase())
}
struct HitPathMetadata {
language_id: String,
symbol_snapshot_id: Option<String>,
canonical_symbol_id: Option<String>,
file_id: Option<String>,
}
fn path_metadata(results: &[CodeRetrievalHit]) -> BTreeMap<String, HitPathMetadata> {
let mut metadata = BTreeMap::new();
for hit in results {
metadata
.entry(hit.path.clone())
.or_insert_with(|| HitPathMetadata {
language_id: hit.language_id.clone(),
symbol_snapshot_id: hit.symbol_snapshot_id.clone(),
canonical_symbol_id: hit.canonical_symbol_id.clone(),
file_id: hit.file_id.clone(),
});
}
metadata
}
fn dedupe_sort_truncate(results: &mut Vec<CodeRetrievalHit>, limit: usize) {
let mut seen = BTreeSet::new();
results
.retain(|hit| seen.insert((hit.path.clone(), hit.line_range.start, hit.excerpt.clone())));
results.sort_by(|left, right| {
right
.score
.total_cmp(&left.score)
.then_with(|| left.path.cmp(&right.path))
.then_with(|| left.line_range.start.cmp(&right.line_range.start))
});
results.truncate(limit);
}
#[cfg(test)]
#[path = "source_fallback_tests.rs"]
mod tests;
#[cfg(test)]
#[path = "source_fallback_reference_tests.rs"]
mod reference_tests;
#[cfg(test)]
#[path = "source_fallback_generated_tests.rs"]
mod generated_tests;
#[cfg(test)]
#[path = "source_fallback_filter_tests.rs"]
mod filter_tests;
#[cfg(test)]
#[path = "source_fallback_surface_tests.rs"]
mod surface_tests;