1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2020-2021, The Tremor Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::lexer;
use crate::{arena, errors::Result};
use crate::{arena::Arena, highlighter::Highlighter};
use crate::{ast::base_expr::Ranged, prelude::*};
use crate::{
ast::{self, helper::Warning, visitors::ConstFolder, walkers::QueryWalker},
lexer::Lexer,
};
use std::collections::BTreeSet;
/// A tremor query
#[derive(Debug, Clone, PartialEq)]
pub struct Query {
/// The query
pub query: ast::Query<'static>,
/// Warnings emitted by the script
pub warnings: BTreeSet<Warning>,
/// Arena index of the string
pub aid: crate::arena::Index,
}
impl<'run, 'event, 'script> Query
where
'script: 'event,
'event: 'run,
{
/// Removes a deploy from the arena, freeing the memory and marking it valid for reause
/// this function generally should not ever be used. It is a special case for the language
/// server where we know that we really only parse the script to check for errors and
/// warnings.
/// That's also why it's behind a feature falg
#[cfg(feature = "arena-delete")]
pub unsafe fn consume_and_free(self) -> Result<()> {
let Query { aid, query, .. } = self;
drop(query);
Arena::delte_index_this_is_really_unsafe_dont_use_it(aid)
}
/// Converts a troy embedded pipeline with resolved arguments to a runnable query
/// # Errors
/// If the query fails to parse and convert correctly
#[must_use]
pub fn from_query(query: ast::Query<'static>) -> Self {
let warnings = BTreeSet::new();
let aid = query.aid();
Self {
query,
warnings,
aid,
}
}
/// Parses a string into a query supporting query arguments
///
/// this is used in the language server to delete lements on a
/// parsing error
///
/// # Errors
/// if the query can not be parsed
#[cfg(feature = "arena-delete")]
pub fn parse_with_aid<S>(
src: &S,
reg: &Registry,
aggr_reg: &AggrRegistry,
) -> std::result::Result<Self, crate::errors::ErrorWithIndex>
where
S: ToString + ?Sized,
{
let (aid, src) = Arena::insert(src)?;
Self::parse_(aid, src, reg, aggr_reg).map_err(|e| crate::errors::ErrorWithIndex(aid, e))
}
/// Parses a string into a query supporting query arguments
///
/// # Errors
/// if the query can not be parsed
pub fn parse<S>(src: &S, reg: &Registry, aggr_reg: &AggrRegistry) -> Result<Self>
where
S: ToString + ?Sized,
{
let (aid, src) = Arena::insert(src)?;
Self::parse_(aid, src, reg, aggr_reg)
}
/// Parses a string into a query supporting query arguments
///
/// # Errors
/// if the query can not be parsed
fn parse_(
aid: arena::Index,
src: &'static str,
reg: &Registry,
aggr_reg: &AggrRegistry,
) -> Result<Self> {
let mut helper = ast::Helper::new(reg, aggr_reg);
let tokens = Lexer::new(src, aid).collect::<Result<Vec<_>>>()?;
let filtered_tokens = tokens.into_iter().filter(|t| !t.value.is_ignorable());
let query_stage_1 = crate::parser::g::QueryParser::new().parse(filtered_tokens)?;
let mut query = query_stage_1.up_script(&mut helper)?;
ConstFolder::new(&helper).walk_query(&mut query)?;
Ok(Self {
query,
warnings: helper.warnings,
aid,
})
}
/// Format an error given a script source.
/// # Errors
/// on io errors
pub fn format_warnings_with<H: Highlighter>(&self, h: &mut H) -> std::io::Result<()> {
for w in &self.warnings {
let tokens: Vec<_> =
lexer::Lexer::new(Arena::io_get(self.query.aid())?, self.query.aid())
.tokenize_until_err()
.collect();
h.highlight_error(None, &tokens, "", true, Some(w.outer), Some(w.into()))?;
}
h.finalize()
}
}