Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-srv/src/server.rs')
-rw-r--r--crates/proc-macro-srv/src/server.rs399
1 files changed, 8 insertions, 391 deletions
diff --git a/crates/proc-macro-srv/src/server.rs b/crates/proc-macro-srv/src/server.rs
index 917d8a6e26..1854322ddb 100644
--- a/crates/proc-macro-srv/src/server.rs
+++ b/crates/proc-macro-srv/src/server.rs
@@ -8,226 +8,18 @@
//!
//! FIXME: No span and source file information is implemented yet
-use proc_macro::bridge::{self, server};
+use proc_macro::bridge;
mod token_stream;
-use proc_macro_api::msg::TokenId;
pub use token_stream::TokenStream;
-use token_stream::TokenStreamBuilder;
+pub mod token_id;
+pub mod rust_analyzer_span;
mod symbol;
pub use symbol::*;
+use tt::Spacing;
-use std::{
- iter,
- ops::{Bound, Range},
-};
-
-use crate::tt;
-
-type Group = tt::Subtree;
-type TokenTree = tt::TokenTree;
-#[allow(unused)]
-type Punct = tt::Punct;
-type Spacing = tt::Spacing;
-#[allow(unused)]
-type Literal = tt::Literal;
-type Span = tt::TokenId;
-
-#[derive(Clone)]
-pub struct SourceFile {
- // FIXME stub
-}
-
-pub struct FreeFunctions;
-
-pub struct RustAnalyzer {
- // FIXME: store span information here.
- pub(crate) interner: SymbolInternerRef,
- pub call_site: TokenId,
- pub def_site: TokenId,
- pub mixed_site: TokenId,
-}
-
-impl server::Types for RustAnalyzer {
- type FreeFunctions = FreeFunctions;
- type TokenStream = TokenStream;
- type SourceFile = SourceFile;
- type Span = Span;
- type Symbol = Symbol;
-}
-
-impl server::FreeFunctions for RustAnalyzer {
- fn injected_env_var(&mut self, _var: &str) -> Option<String> {
- None
- }
-
- fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {
- // FIXME: track env var accesses
- // https://github.com/rust-lang/rust/pull/71858
- }
- fn track_path(&mut self, _path: &str) {}
-
- fn literal_from_str(
- &mut self,
- s: &str,
- ) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
- // FIXME: keep track of LitKind and Suffix
- Ok(bridge::Literal {
- kind: bridge::LitKind::Err,
- symbol: Symbol::intern(self.interner, s),
- suffix: None,
- span: self.call_site,
- })
- }
-
- fn emit_diagnostic(&mut self, _: bridge::Diagnostic<Self::Span>) {
- // FIXME handle diagnostic
- }
-}
-
-impl server::TokenStream for RustAnalyzer {
- fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
- stream.is_empty()
- }
- fn from_str(&mut self, src: &str) -> Self::TokenStream {
- Self::TokenStream::from_str(src, self.call_site).expect("cannot parse string")
- }
- fn to_string(&mut self, stream: &Self::TokenStream) -> String {
- stream.to_string()
- }
- fn from_token_tree(
- &mut self,
- tree: bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>,
- ) -> Self::TokenStream {
- match tree {
- bridge::TokenTree::Group(group) => {
- let group = Group {
- delimiter: delim_to_internal(group.delimiter, group.span),
- token_trees: match group.stream {
- Some(stream) => stream.into_iter().collect(),
- None => Vec::new(),
- },
- };
- let tree = TokenTree::from(group);
- Self::TokenStream::from_iter(iter::once(tree))
- }
-
- bridge::TokenTree::Ident(ident) => {
- let text = ident.sym.text(self.interner);
- let text =
- if ident.is_raw { ::tt::SmolStr::from_iter(["r#", &text]) } else { text };
- let ident: tt::Ident = tt::Ident { text, span: ident.span };
- let leaf = tt::Leaf::from(ident);
- let tree = TokenTree::from(leaf);
- Self::TokenStream::from_iter(iter::once(tree))
- }
-
- bridge::TokenTree::Literal(literal) => {
- let literal = LiteralFormatter(literal);
- let text = literal.with_stringify_parts(self.interner, |parts| {
- ::tt::SmolStr::from_iter(parts.iter().copied())
- });
-
- let literal = tt::Literal { text, span: literal.0.span };
- let leaf = tt::Leaf::from(literal);
- let tree = TokenTree::from(leaf);
- Self::TokenStream::from_iter(iter::once(tree))
- }
-
- bridge::TokenTree::Punct(p) => {
- let punct = tt::Punct {
- char: p.ch as char,
- spacing: if p.joint { Spacing::Joint } else { Spacing::Alone },
- span: p.span,
- };
- let leaf = tt::Leaf::from(punct);
- let tree = TokenTree::from(leaf);
- Self::TokenStream::from_iter(iter::once(tree))
- }
- }
- }
-
- fn expand_expr(&mut self, self_: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
- Ok(self_.clone())
- }
-
- fn concat_trees(
- &mut self,
- base: Option<Self::TokenStream>,
- trees: Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>>,
- ) -> Self::TokenStream {
- let mut builder = TokenStreamBuilder::new();
- if let Some(base) = base {
- builder.push(base);
- }
- for tree in trees {
- builder.push(self.from_token_tree(tree));
- }
- builder.build()
- }
-
- fn concat_streams(
- &mut self,
- base: Option<Self::TokenStream>,
- streams: Vec<Self::TokenStream>,
- ) -> Self::TokenStream {
- let mut builder = TokenStreamBuilder::new();
- if let Some(base) = base {
- builder.push(base);
- }
- for stream in streams {
- builder.push(stream);
- }
- builder.build()
- }
-
- fn into_trees(
- &mut self,
- stream: Self::TokenStream,
- ) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
- stream
- .into_iter()
- .map(|tree| match tree {
- tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
- bridge::TokenTree::Ident(bridge::Ident {
- sym: Symbol::intern(self.interner, ident.text.trim_start_matches("r#")),
- is_raw: ident.text.starts_with("r#"),
- span: ident.span,
- })
- }
- tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
- bridge::TokenTree::Literal(bridge::Literal {
- // FIXME: handle literal kinds
- kind: bridge::LitKind::Err,
- symbol: Symbol::intern(self.interner, &lit.text),
- // FIXME: handle suffixes
- suffix: None,
- span: lit.span,
- })
- }
- tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => {
- bridge::TokenTree::Punct(bridge::Punct {
- ch: punct.char as u8,
- joint: punct.spacing == Spacing::Joint,
- span: punct.span,
- })
- }
- tt::TokenTree::Subtree(subtree) => bridge::TokenTree::Group(bridge::Group {
- delimiter: delim_to_external(subtree.delimiter),
- stream: if subtree.token_trees.is_empty() {
- None
- } else {
- Some(subtree.token_trees.into_iter().collect())
- },
- span: bridge::DelimSpan::from_single(subtree.delimiter.open),
- }),
- })
- .collect()
- }
-}
-
-fn delim_to_internal(d: proc_macro::Delimiter, span: bridge::DelimSpan<Span>) -> tt::Delimiter {
+fn delim_to_internal<S>(d: proc_macro::Delimiter, span: bridge::DelimSpan<S>) -> tt::Delimiter<S> {
let kind = match d {
proc_macro::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
proc_macro::Delimiter::Brace => tt::DelimiterKind::Brace,
@@ -237,7 +29,7 @@ fn delim_to_internal(d: proc_macro::Delimiter, span: bridge::DelimSpan<Span>) ->
tt::Delimiter { open: span.open, close: span.close, kind }
}
-fn delim_to_external(d: tt::Delimiter) -> proc_macro::Delimiter {
+fn delim_to_external<S>(d: tt::Delimiter<S>) -> proc_macro::Delimiter {
match d.kind {
tt::DelimiterKind::Parenthesis => proc_macro::Delimiter::Parenthesis,
tt::DelimiterKind::Brace => proc_macro::Delimiter::Brace,
@@ -262,121 +54,9 @@ fn spacing_to_external(spacing: Spacing) -> proc_macro::Spacing {
}
}
-impl server::SourceFile for RustAnalyzer {
- // FIXME these are all stubs
- fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool {
- true
- }
- fn path(&mut self, _file: &Self::SourceFile) -> String {
- String::new()
- }
- fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
- true
- }
-}
-
-impl server::Span for RustAnalyzer {
- fn debug(&mut self, span: Self::Span) -> String {
- format!("{:?}", span.0)
- }
- fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
- SourceFile {}
- }
- fn save_span(&mut self, _span: Self::Span) -> usize {
- // FIXME stub
- 0
- }
- fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span {
- // FIXME stub
- self.call_site
- }
- /// Recent feature, not yet in the proc_macro
- ///
- /// See PR:
- /// https://github.com/rust-lang/rust/pull/55780
- fn source_text(&mut self, _span: Self::Span) -> Option<String> {
- None
- }
-
- fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
- // FIXME handle span
- None
- }
- fn source(&mut self, span: Self::Span) -> Self::Span {
- // FIXME handle span
- span
- }
- fn byte_range(&mut self, _span: Self::Span) -> Range<usize> {
- // FIXME handle span
- Range { start: 0, end: 0 }
- }
- fn join(&mut self, first: Self::Span, _second: Self::Span) -> Option<Self::Span> {
- // Just return the first span again, because some macros will unwrap the result.
- Some(first)
- }
- fn subspan(
- &mut self,
- span: Self::Span,
- _start: Bound<usize>,
- _end: Bound<usize>,
- ) -> Option<Self::Span> {
- // Just return the span again, because some macros will unwrap the result.
- Some(span)
- }
- fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span {
- // FIXME handle span
- self.call_site
- }
-
- fn end(&mut self, _self_: Self::Span) -> Self::Span {
- self.call_site
- }
-
- fn start(&mut self, _self_: Self::Span) -> Self::Span {
- self.call_site
- }
-
- fn line(&mut self, _span: Self::Span) -> usize {
- // FIXME handle line
- 0
- }
-
- fn column(&mut self, _span: Self::Span) -> usize {
- // FIXME handle column
- 0
- }
-}
-
-impl server::Symbol for RustAnalyzer {
- fn normalize_and_validate_ident(&mut self, string: &str) -> Result<Self::Symbol, ()> {
- // FIXME: nfc-normalize and validate idents
- Ok(<Self as server::Server>::intern_symbol(string))
- }
-}
-
-impl server::Server for RustAnalyzer {
- fn globals(&mut self) -> bridge::ExpnGlobals<Self::Span> {
- bridge::ExpnGlobals {
- def_site: self.def_site,
- call_site: self.call_site,
- mixed_site: self.mixed_site,
- }
- }
-
- fn intern_symbol(ident: &str) -> Self::Symbol {
- // FIXME: should be `self.interner` once the proc-macro api allows it.
- Symbol::intern(&SYMBOL_INTERNER, &::tt::SmolStr::from(ident))
- }
-
- fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
- // FIXME: should be `self.interner` once the proc-macro api allows it.
- f(symbol.text(&SYMBOL_INTERNER).as_str())
- }
-}
-
-struct LiteralFormatter(bridge::Literal<tt::TokenId, Symbol>);
+struct LiteralFormatter<S>(bridge::Literal<S, Symbol>);
-impl LiteralFormatter {
+impl<S> LiteralFormatter<S> {
/// Invokes the callback with a `&[&str]` consisting of each part of the
/// literal's representation. This is done to allow the `ToString` and
/// `Display` implementations to borrow references to symbol values, and
@@ -427,66 +107,3 @@ impl LiteralFormatter {
f(symbol.as_str(), suffix.as_str())
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_ra_server_to_string() {
- let s = TokenStream {
- token_trees: vec![
- tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "struct".into(),
- span: tt::TokenId(0),
- })),
- tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "T".into(),
- span: tt::TokenId(0),
- })),
- tt::TokenTree::Subtree(tt::Subtree {
- delimiter: tt::Delimiter {
- open: tt::TokenId(0),
- close: tt::TokenId(0),
- kind: tt::DelimiterKind::Brace,
- },
- token_trees: vec![],
- }),
- ],
- };
-
- assert_eq!(s.to_string(), "struct T {}");
- }
-
- #[test]
- fn test_ra_server_from_str() {
- let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
- delimiter: tt::Delimiter {
- open: tt::TokenId(0),
- close: tt::TokenId(0),
- kind: tt::DelimiterKind::Parenthesis,
- },
- token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "a".into(),
- span: tt::TokenId(0),
- }))],
- });
-
- let t1 = TokenStream::from_str("(a)", tt::TokenId(0)).unwrap();
- assert_eq!(t1.token_trees.len(), 1);
- assert_eq!(t1.token_trees[0], subtree_paren_a);
-
- let t2 = TokenStream::from_str("(a);", tt::TokenId(0)).unwrap();
- assert_eq!(t2.token_trees.len(), 2);
- assert_eq!(t2.token_trees[0], subtree_paren_a);
-
- let underscore = TokenStream::from_str("_", tt::TokenId(0)).unwrap();
- assert_eq!(
- underscore.token_trees[0],
- tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "_".into(),
- span: tt::TokenId(0),
- }))
- );
- }
-}