mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Merge commit '457b966b17
' into sync-from-ra
This commit is contained in:
parent
5285df4f6c
commit
f532576ac5
263 changed files with 9788 additions and 6258 deletions
|
@ -121,6 +121,7 @@ impl ast::Whitespace {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QuoteOffsets {
|
||||
pub quotes: (TextRange, TextRange),
|
||||
pub contents: TextRange,
|
||||
|
@ -167,6 +168,11 @@ pub trait IsString: AstToken {
|
|||
fn text_range_between_quotes(&self) -> Option<TextRange> {
|
||||
self.quote_offsets().map(|it| it.contents)
|
||||
}
|
||||
fn text_without_quotes(&self) -> &str {
|
||||
let text = self.text();
|
||||
let Some(offsets) = self.text_range_between_quotes() else { return text };
|
||||
&text[offsets - self.syntax().text_range().start()]
|
||||
}
|
||||
fn open_quote_text_range(&self) -> Option<TextRange> {
|
||||
self.quote_offsets().map(|it| it.quotes.0)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md>
|
||||
|
||||
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! eprintln {
|
||||
|
@ -75,7 +75,7 @@ pub use smol_str::SmolStr;
|
|||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Parse<T> {
|
||||
green: GreenNode,
|
||||
errors: Arc<[SyntaxError]>,
|
||||
errors: Option<Arc<[SyntaxError]>>,
|
||||
_ty: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
|
@ -87,14 +87,18 @@ impl<T> Clone for Parse<T> {
|
|||
|
||||
impl<T> Parse<T> {
|
||||
fn new(green: GreenNode, errors: Vec<SyntaxError>) -> Parse<T> {
|
||||
Parse { green, errors: errors.into(), _ty: PhantomData }
|
||||
Parse {
|
||||
green,
|
||||
errors: if errors.is_empty() { None } else { Some(errors.into()) },
|
||||
_ty: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn syntax_node(&self) -> SyntaxNode {
|
||||
SyntaxNode::new_root(self.green.clone())
|
||||
}
|
||||
pub fn errors(&self) -> &[SyntaxError] {
|
||||
&self.errors
|
||||
self.errors.as_deref().unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,10 +112,9 @@ impl<T: AstNode> Parse<T> {
|
|||
}
|
||||
|
||||
pub fn ok(self) -> Result<T, Arc<[SyntaxError]>> {
|
||||
if self.errors.is_empty() {
|
||||
Ok(self.tree())
|
||||
} else {
|
||||
Err(self.errors)
|
||||
match self.errors {
|
||||
Some(e) => Err(e),
|
||||
None => Ok(self.tree()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +132,7 @@ impl Parse<SyntaxNode> {
|
|||
impl Parse<SourceFile> {
|
||||
pub fn debug_dump(&self) -> String {
|
||||
let mut buf = format!("{:#?}", self.tree().syntax());
|
||||
for err in self.errors.iter() {
|
||||
for err in self.errors.as_deref().into_iter().flat_map(<[_]>::iter) {
|
||||
format_to!(buf, "error {:?}: {}\n", err.range(), err);
|
||||
}
|
||||
buf
|
||||
|
@ -141,13 +144,16 @@ impl Parse<SourceFile> {
|
|||
|
||||
fn incremental_reparse(&self, indel: &Indel) -> Option<Parse<SourceFile>> {
|
||||
// FIXME: validation errors are not handled here
|
||||
parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map(
|
||||
|(green_node, errors, _reparsed_range)| Parse {
|
||||
green: green_node,
|
||||
errors: errors.into(),
|
||||
_ty: PhantomData,
|
||||
},
|
||||
parsing::incremental_reparse(
|
||||
self.tree().syntax(),
|
||||
indel,
|
||||
self.errors.as_deref().unwrap_or_default().iter().cloned(),
|
||||
)
|
||||
.map(|(green_node, errors, _reparsed_range)| Parse {
|
||||
green: green_node,
|
||||
errors: if errors.is_empty() { None } else { Some(errors.into()) },
|
||||
_ty: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn full_reparse(&self, indel: &Indel) -> Parse<SourceFile> {
|
||||
|
@ -168,7 +174,11 @@ impl SourceFile {
|
|||
errors.extend(validation::validate(&root));
|
||||
|
||||
assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE);
|
||||
Parse { green, errors: errors.into(), _ty: PhantomData }
|
||||
Parse {
|
||||
green,
|
||||
errors: if errors.is_empty() { None } else { Some(errors.into()) },
|
||||
_ty: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +285,11 @@ impl ast::TokenTree {
|
|||
|
||||
let (green, errors) = builder.finish_raw();
|
||||
|
||||
Parse { green, errors: errors.into(), _ty: PhantomData }
|
||||
Parse {
|
||||
green,
|
||||
errors: if errors.is_empty() { None } else { Some(errors.into()) },
|
||||
_ty: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
|||
pub(crate) fn incremental_reparse(
|
||||
node: &SyntaxNode,
|
||||
edit: &Indel,
|
||||
errors: Vec<SyntaxError>,
|
||||
errors: impl IntoIterator<Item = SyntaxError>,
|
||||
) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
|
||||
if let Some((green, new_errors, old_range)) = reparse_token(node, edit) {
|
||||
return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
|
||||
|
@ -147,7 +147,7 @@ fn is_balanced(lexed: &parser::LexedStr<'_>) -> bool {
|
|||
}
|
||||
|
||||
fn merge_errors(
|
||||
old_errors: Vec<SyntaxError>,
|
||||
old_errors: impl IntoIterator<Item = SyntaxError>,
|
||||
new_errors: Vec<SyntaxError>,
|
||||
range_before_reparse: TextRange,
|
||||
edit: &Indel,
|
||||
|
@ -191,8 +191,12 @@ mod tests {
|
|||
let fully_reparsed = SourceFile::parse(&after);
|
||||
let incrementally_reparsed: Parse<SourceFile> = {
|
||||
let before = SourceFile::parse(&before);
|
||||
let (green, new_errors, range) =
|
||||
incremental_reparse(before.tree().syntax(), &edit, before.errors.to_vec()).unwrap();
|
||||
let (green, new_errors, range) = incremental_reparse(
|
||||
before.tree().syntax(),
|
||||
&edit,
|
||||
before.errors.as_deref().unwrap_or_default().iter().cloned(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
|
||||
Parse::new(green, new_errors)
|
||||
};
|
||||
|
|
|
@ -22,12 +22,18 @@ use crate::{syntax_node::RustLanguage, AstNode, SyntaxNode};
|
|||
pub type SyntaxNodePtr = rowan::ast::SyntaxNodePtr<RustLanguage>;
|
||||
|
||||
/// Like `SyntaxNodePtr`, but remembers the type of node.
|
||||
#[derive(Debug)]
|
||||
pub struct AstPtr<N: AstNode> {
|
||||
raw: SyntaxNodePtr,
|
||||
_ty: PhantomData<fn() -> N>,
|
||||
}
|
||||
|
||||
impl<N: AstNode + std::fmt::Debug> std::fmt::Debug for AstPtr<N> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("AstPtr").field(&self.raw).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: AstNode> Copy for AstPtr<N> {}
|
||||
impl<N: AstNode> Clone for AstPtr<N> {
|
||||
fn clone(&self) -> AstPtr<N> {
|
||||
AstPtr { raw: self.raw.clone(), _ty: PhantomData }
|
||||
|
|
|
@ -38,7 +38,7 @@ fn benchmark_parser() {
|
|||
let tree = {
|
||||
let _b = bench("parsing");
|
||||
let p = SourceFile::parse(&data);
|
||||
assert!(p.errors.is_empty());
|
||||
assert!(p.errors.is_none());
|
||||
assert_eq!(p.tree().syntax.text_range().len(), 352474.into());
|
||||
p.tree()
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ pub(crate) enum Repr<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TokenText<'a> {
|
||||
pub(crate) fn borrowed(text: &'a str) -> Self {
|
||||
pub fn borrowed(text: &'a str) -> Self {
|
||||
TokenText(Repr::Borrowed(text))
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue