aboutsummaryrefslogtreecommitdiff
path: root/libeditor/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libeditor/src/lib.rs')
-rw-r--r--libeditor/src/lib.rs165
1 files changed, 77 insertions, 88 deletions
diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs
index 5ebb49139..817a2d15b 100644
--- a/libeditor/src/lib.rs
+++ b/libeditor/src/lib.rs
@@ -6,13 +6,10 @@ use libsyntax2::{
6 SyntaxNodeRef, AstNode, 6 SyntaxNodeRef, AstNode,
7 algo::walk, 7 algo::walk,
8 SyntaxKind::*, 8 SyntaxKind::*,
9 ast,
9}; 10};
10pub use libsyntax2::{TextRange, TextUnit}; 11pub use libsyntax2::{TextRange, TextUnit};
11 12
12pub struct File {
13 inner: libsyntax2::File
14}
15
16#[derive(Debug)] 13#[derive(Debug)]
17pub struct HighlightedRange { 14pub struct HighlightedRange {
18 pub range: TextRange, 15 pub range: TextRange,
@@ -44,103 +41,95 @@ pub enum RunnableKind {
44 Bin, 41 Bin,
45} 42}
46 43
47impl File { 44pub fn highlight(file: &ast::File) -> Vec<HighlightedRange> {
48 pub fn new(text: &str) -> File { 45 let syntax = file.syntax();
49 File { 46 let mut res = Vec::new();
50 inner: libsyntax2::File::parse(text) 47 for node in walk::preorder(syntax.as_ref()) {
51 } 48 let tag = match node.kind() {
49 ERROR => "error",
50 COMMENT | DOC_COMMENT => "comment",
51 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string",
52 ATTR => "attribute",
53 NAME_REF => "text",
54 NAME => "function",
55 INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal",
56 LIFETIME => "parameter",
57 k if k.is_keyword() => "keyword",
58 _ => continue,
59 };
60 res.push(HighlightedRange {
61 range: node.range(),
62 tag,
63 })
52 } 64 }
65 res
66}
53 67
54 pub fn highlight(&self) -> Vec<HighlightedRange> { 68pub fn diagnostics(file: &ast::File) -> Vec<Diagnostic> {
55 let syntax = self.inner.syntax(); 69 let syntax = file.syntax();
56 let mut res = Vec::new(); 70 let mut res = Vec::new();
57 for node in walk::preorder(syntax.as_ref()) {
58 let tag = match node.kind() {
59 ERROR => "error",
60 COMMENT | DOC_COMMENT => "comment",
61 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string",
62 ATTR => "attribute",
63 NAME_REF => "text",
64 NAME => "function",
65 INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal",
66 LIFETIME => "parameter",
67 k if k.is_keyword() => "keyword",
68 _ => continue,
69 };
70 res.push(HighlightedRange {
71 range: node.range(),
72 tag,
73 })
74 }
75 res
76 }
77 71
78 pub fn diagnostics(&self) -> Vec<Diagnostic> { 72 for node in walk::preorder(syntax.as_ref()) {
79 let syntax = self.inner.syntax(); 73 if node.kind() == ERROR {
80 let mut res = Vec::new(); 74 res.push(Diagnostic {
81 75 range: node.range(),
82 for node in walk::preorder(syntax.as_ref()) { 76 msg: "Syntax Error".to_string(),
83 if node.kind() == ERROR { 77 });
84 res.push(Diagnostic {
85 range: node.range(),
86 msg: "Syntax Error".to_string(),
87 });
88 }
89 } 78 }
90 res.extend(self.inner.errors().into_iter().map(|err| Diagnostic {
91 range: TextRange::offset_len(err.offset, 1.into()),
92 msg: err.msg,
93 }));
94 res
95 } 79 }
80 res.extend(file.errors().into_iter().map(|err| Diagnostic {
81 range: TextRange::offset_len(err.offset, 1.into()),
82 msg: err.msg,
83 }));
84 res
85}
96 86
97 pub fn syntax_tree(&self) -> String { 87pub fn syntax_tree(file: &ast::File) -> String {
98 ::libsyntax2::utils::dump_tree(&self.inner.syntax()) 88 ::libsyntax2::utils::dump_tree(&file.syntax())
99 } 89}
100 90
101 pub fn symbols(&self) -> Vec<Symbol> { 91pub fn symbols(file: &ast::File) -> Vec<Symbol> {
102 let syntax = self.inner.syntax(); 92 let syntax = file.syntax();
103 let res: Vec<Symbol> = walk::preorder(syntax.as_ref()) 93 let res: Vec<Symbol> = walk::preorder(syntax.as_ref())
104 .filter_map(Declaration::cast) 94 .filter_map(Declaration::cast)
105 .filter_map(|decl| { 95 .filter_map(|decl| {
106 let name = decl.name()?; 96 let name = decl.name()?;
107 let range = decl.range(); 97 let range = decl.range();
108 Some(Symbol { name, range }) 98 Some(Symbol { name, range })
109 }) 99 })
110 .collect(); 100 .collect();
111 res // NLL :-( 101 res // NLL :-(
112 } 102}
113 103
114 pub fn extend_selection(&self, range: TextRange) -> Option<TextRange> { 104pub fn extend_selection(file: &ast::File, range: TextRange) -> Option<TextRange> {
115 let syntax = self.inner.syntax(); 105 let syntax = file.syntax();
116 extend_selection::extend_selection(syntax.as_ref(), range) 106 extend_selection::extend_selection(syntax.as_ref(), range)
117 } 107}
118 108
119 pub fn runnables(&self) -> Vec<Runnable> { 109pub fn runnables(file: &ast::File) -> Vec<Runnable> {
120 self.inner 110 file
121 .functions() 111 .functions()
122 .filter_map(|f| { 112 .filter_map(|f| {
123 let name = f.name()?.text(); 113 let name = f.name()?.text();
124 let kind = if name == "main" { 114 let kind = if name == "main" {
125 RunnableKind::Bin 115 RunnableKind::Bin
126 } else if f.has_atom_attr("test") { 116 } else if f.has_atom_attr("test") {
127 RunnableKind::Test { 117 RunnableKind::Test {
128 name: name.to_string() 118 name: name.to_string()
129 } 119 }
130 } else { 120 } else {
131 return None; 121 return None;
132 }; 122 };
133 Some(Runnable { 123 Some(Runnable {
134 range: f.syntax().range(), 124 range: f.syntax().range(),
135 kind, 125 kind,
136 })
137 }) 126 })
138 .collect() 127 })
139 } 128 .collect()
140} 129}
141 130
142 131
143struct Declaration<'f>(SyntaxNodeRef<'f>); 132struct Declaration<'f> (SyntaxNodeRef<'f>);
144 133
145impl<'f> Declaration<'f> { 134impl<'f> Declaration<'f> {
146 fn cast(node: SyntaxNodeRef<'f>) -> Option<Declaration<'f>> { 135 fn cast(node: SyntaxNodeRef<'f>) -> Option<Declaration<'f>> {