дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-11 20:25:41 +02:00
Порівняти коміти
1
Коміти
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
cbcd1818a7 |
No files matched your search
@@ -121,9 +121,14 @@ pub(crate) struct NavigationIndex {
|
||||
fn contains(range: Range, pos: Pos) -> bool {
|
||||
(range.start.line, range.start.col) <= (pos.line, pos.col) && (pos.line, pos.col) < (range.end.line, range.end.col)
|
||||
}
|
||||
/// Inside the document, start not after end. An empty range marks a position (a template file's
|
||||
/// definition at its start, say): navigation lands there, but it has no text to rename.
|
||||
fn valid_range(lines: &[usize], range: Range) -> bool {
|
||||
let pos = |p: Pos| lines.get(p.line as usize).is_some_and(|&length| p.col as usize <= length);
|
||||
pos(range.start) && pos(range.end) && (range.start.line, range.start.col) < (range.end.line, range.end.col)
|
||||
pos(range.start) && pos(range.end) && (range.start.line, range.start.col) <= (range.end.line, range.end.col)
|
||||
}
|
||||
fn is_empty(range: Range) -> bool {
|
||||
(range.start.line, range.start.col) == (range.end.line, range.end.col)
|
||||
}
|
||||
|
||||
impl PluginHost {
|
||||
@@ -280,12 +285,20 @@ impl PluginHost {
|
||||
.chain(&edges.references)
|
||||
.any(|a| a.key.is_empty() || a.key.len() > 1024 || !valid_range(&lines, a.range))
|
||||
{
|
||||
return Err(IdeError::invalid("invalid navigation anchors"));
|
||||
return Err(IdeError::invalid(format!(
|
||||
"{}: invalid navigation anchors in {}",
|
||||
plugin.id(),
|
||||
path.display()
|
||||
)));
|
||||
}
|
||||
if edges.markers.len() > MAX_EDGES
|
||||
|| edges.markers.iter().any(|a| a.key.is_empty() || a.key.len() > 1024 || !valid_range(&lines, a.range))
|
||||
{
|
||||
return Err(IdeError::invalid("invalid navigation markers"));
|
||||
return Err(IdeError::invalid(format!(
|
||||
"{}: invalid navigation markers in {}",
|
||||
plugin.id(),
|
||||
path.display()
|
||||
)));
|
||||
}
|
||||
let mut index = self.navigation.lock();
|
||||
if index.epochs.get(root).copied() != generation {
|
||||
@@ -406,7 +419,7 @@ impl PluginHost {
|
||||
let answer = result.get_or_insert_with(|| IndexedSymbol { range: primary.range, files: vec![] });
|
||||
for (path, file) in &graph.files {
|
||||
let mut ranges = std::collections::BTreeSet::new();
|
||||
for candidate in &file.edges.definitions {
|
||||
for candidate in file.edges.definitions.iter().filter(|a| !is_empty(a.range)) {
|
||||
if targets.contains(&Location::file(path.clone(), candidate.range))
|
||||
|| (targets.is_empty() && file.scope == source.scope && keys.contains(candidate.key.as_str()))
|
||||
{
|
||||
@@ -414,7 +427,7 @@ impl PluginHost {
|
||||
}
|
||||
}
|
||||
let mut matches = HashMap::new();
|
||||
for candidate in &file.edges.references {
|
||||
for candidate in file.edges.references.iter().filter(|a| !is_empty(a.range)) {
|
||||
let same = *matches.entry(candidate.key.as_str()).or_insert_with(|| {
|
||||
let resolved = graph.scoped_targets(&candidate.key, &file.scope);
|
||||
resolved.iter().any(|target| targets.contains(target))
|
||||
@@ -580,3 +593,21 @@ impl ExtensionPoint for IndexersPoint {
|
||||
Ok(Prepared::new(d.extensions.join(", "), || Ok(Disposable::new(|| {}))).capability(Capability::ProjectRead))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn empty_ranges_inside_the_document_are_valid_positions() {
|
||||
let lines = [3, 0];
|
||||
let range = |a: (u32, u32), b: (u32, u32)| Range::new(Pos::new(a.0, a.1), Pos::new(b.0, b.1));
|
||||
assert!(valid_range(&lines, range((0, 0), (0, 0))));
|
||||
assert!(valid_range(&lines, range((1, 0), (1, 0))));
|
||||
assert!(valid_range(&lines, range((0, 1), (0, 3))));
|
||||
assert!(!valid_range(&lines, range((0, 2), (0, 1))), "reversed");
|
||||
assert!(!valid_range(&lines, range((0, 4), (0, 4))), "past the line end");
|
||||
assert!(!valid_range(&lines, range((2, 0), (2, 0))), "past the last line");
|
||||
assert!(is_empty(range((0, 0), (0, 0))) && !is_empty(range((0, 0), (0, 1))));
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,9 @@ interface document-indexer {
|
||||
|
||||
/// A range of the document tied to a key the plugin chooses
|
||||
/// (`com.example.UserMapper#findById`, say). Keys are compared as is.
|
||||
/// Ranges lie inside the document; an empty one marks a position (a
|
||||
/// definition that is the whole file, at its start): Go to Declaration
|
||||
/// lands there, Find Usages and Rename skip it.
|
||||
record anchor {
|
||||
key: string,
|
||||
range: range,
|
||||
|
||||
@@ -29,6 +29,9 @@ interface document-indexer {
|
||||
|
||||
/// A range of the document tied to a key the plugin chooses
|
||||
/// (`com.example.UserMapper#findById`, say). Keys are compared as is.
|
||||
/// Ranges lie inside the document; an empty one marks a position (a
|
||||
/// definition that is the whole file, at its start): Go to Declaration
|
||||
/// lands there, Find Usages and Rename skip it.
|
||||
record anchor {
|
||||
key: string,
|
||||
range: range,
|
||||
|
||||
Reference in new issue
Заблокувати користувача