clang/
sonar.rs

1// Copyright 2016 Kyle Mayes
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Finding C declarations.
16
17use std::vec;
18use std::collections::{HashSet};
19use std::str::{FromStr};
20
21use super::{Entity, EntityKind, Type, TypeKind};
22
23//================================================
24// Enums
25//================================================
26
27// DefinitionValue _______________________________
28
29/// The value of a C preprocessor definition.
30#[derive(Copy, Clone, Debug, PartialEq)]
31pub enum DefinitionValue {
32    /// An integer.
33    Integer(bool, u64),
34    /// A floating point number.
35    Real(f64),
36}
37
38impl DefinitionValue {
39    //- Constructors -----------------------------
40
41    fn from_entity(entity: Entity) -> Option<DefinitionValue> {
42        let mut tokens = entity.get_range().unwrap().tokenize();
43        if tokens.last().map_or(false, |t| t.get_spelling() == "#") {
44            tokens.pop();
45        }
46
47        let (negated, number) = if tokens.len() == 2 {
48            (false, tokens[1].get_spelling())
49        } else if tokens.len() == 3 && tokens[1].get_spelling() == "-" {
50            (true, tokens[2].get_spelling())
51        } else {
52            return None;
53        };
54
55        if let Ok(integer) = u64::from_str(&number) {
56            Some(DefinitionValue::Integer(negated, integer))
57        } else if let Ok(real) = f64::from_str(&number) {
58            if negated {
59                Some(DefinitionValue::Real(-real))
60            } else {
61                Some(DefinitionValue::Real(real))
62            }
63        } else {
64            None
65        }
66    }
67}
68
69//================================================
70// Structs
71//================================================
72
73// Declaration ___________________________________
74
75/// A C declaration.
76#[derive(Clone, Debug, PartialEq, Eq)]
77pub struct Declaration<'tu> {
78    /// The name of the declaration.
79    pub name: String,
80    /// The entity that describes the declaration (e.g., contains the fields of a struct).
81    pub entity: Entity<'tu>,
82    /// The entity the declaration originated from if it differs from `entity`.
83    pub source: Option<Entity<'tu>>,
84}
85
86impl<'tu> Declaration<'tu> {
87    //- Constructors -----------------------------
88
89    fn new(name: String, entity: Entity<'tu>, source: Option<Entity<'tu>>) -> Declaration<'tu> {
90        Declaration { name, entity, source }
91    }
92}
93
94// Definition ____________________________________
95
96/// A C preprocessor definition.
97#[derive(Clone, Debug, PartialEq)]
98pub struct Definition<'tu> {
99    /// The name of the definition.
100    pub name: String,
101    /// The value of the definition.
102    pub value: DefinitionValue,
103    /// The entity that describes the definition.
104    pub entity: Entity<'tu>,
105}
106
107impl<'tu> Definition<'tu> {
108    //- Constructors -----------------------------
109
110    fn new(name: String, value: DefinitionValue, entity: Entity<'tu>) -> Definition<'tu> {
111        Definition { name, value, entity }
112    }
113}
114
115// Definitions ___________________________________
116
117/// An iterator over preprocessor definition declarations.
118#[allow(missing_debug_implementations)]
119pub struct Definitions<'tu> {
120    entities: vec::IntoIter<Entity<'tu>>,
121    seen: HashSet<String>,
122}
123
124impl<'tu> Definitions<'tu> {
125    //- Constructors -----------------------------
126
127    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Definitions<'tu> {
128        Definitions { entities, seen: HashSet::new() }
129    }
130}
131
132impl<'tu> Iterator for Definitions<'tu> {
133    type Item = Definition<'tu>;
134
135    fn next(&mut self) -> Option<Definition<'tu>> {
136        for entity in &mut self.entities {
137            if entity.get_kind() == EntityKind::MacroDefinition {
138                let name = entity.get_name().unwrap();
139                if !self.seen.contains(&name) {
140                    if let Some(value) = DefinitionValue::from_entity(entity) {
141                        self.seen.insert(name.clone());
142                        return Some(Definition::new(name, value, entity));
143                    }
144                }
145            }
146        }
147        None
148    }
149}
150
151// Enums _________________________________________
152
153/// An iterator over enum declarations.
154#[allow(missing_debug_implementations)]
155pub struct Enums<'tu> {
156    entities: vec::IntoIter<Entity<'tu>>,
157    seen: HashSet<String>,
158}
159
160impl<'tu> Enums<'tu> {
161    //- Constructors -----------------------------
162
163    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Enums<'tu> {
164        Enums { entities, seen: HashSet::new() }
165    }
166}
167
168impl<'tu> Iterator for Enums<'tu> {
169    type Item = Declaration<'tu>;
170
171    fn next(&mut self) -> Option<Declaration<'tu>> {
172        next(&mut self.entities, &mut self.seen, EntityKind::EnumDecl, "enum ")
173    }
174}
175
176// Functions _____________________________________
177
178/// An iterator over function declarations.
179#[allow(missing_debug_implementations)]
180pub struct Functions<'tu> {
181    entities: vec::IntoIter<Entity<'tu>>,
182    seen: HashSet<String>,
183}
184
185impl<'tu> Functions<'tu> {
186    //- Constructors -----------------------------
187
188    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Functions<'tu> {
189        Functions { entities, seen: HashSet::new() }
190    }
191}
192
193impl<'tu> Iterator for Functions<'tu> {
194    type Item = Declaration<'tu>;
195
196    fn next(&mut self) -> Option<Declaration<'tu>> {
197        for entity in &mut self.entities {
198            if entity.get_kind() == EntityKind::FunctionDecl {
199                let name = entity.get_name().unwrap();
200                if !self.seen.contains(&name) {
201                    self.seen.insert(name.clone());
202                    return Some(Declaration::new(name, entity, None));
203                }
204            }
205        }
206        None
207    }
208}
209
210// Structs _______________________________________
211
212/// An iterator over struct declarations.
213#[allow(missing_debug_implementations)]
214pub struct Structs<'tu> {
215    entities: vec::IntoIter<Entity<'tu>>,
216    seen: HashSet<String>,
217}
218
219impl<'tu> Structs<'tu> {
220    //- Constructors -----------------------------
221
222    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Structs<'tu> {
223        Structs { entities, seen: HashSet::new() }
224    }
225}
226
227impl<'tu> Iterator for Structs<'tu> {
228    type Item = Declaration<'tu>;
229
230    fn next(&mut self) -> Option<Declaration<'tu>> {
231        next(&mut self.entities, &mut self.seen, EntityKind::StructDecl, "struct ")
232    }
233}
234
235// Typedefs ______________________________________
236
237/// An iterator over typedef declarations.
238#[allow(missing_debug_implementations)]
239pub struct Typedefs<'tu> {
240    entities: vec::IntoIter<Entity<'tu>>,
241    seen: HashSet<String>,
242}
243
244impl<'tu> Typedefs<'tu> {
245    //- Constructors -----------------------------
246
247    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Typedefs<'tu> {
248        Typedefs { entities, seen: HashSet::new() }
249    }
250}
251
252impl<'tu> Iterator for Typedefs<'tu> {
253    type Item = Declaration<'tu>;
254
255    fn next(&mut self) -> Option<Declaration<'tu>> {
256        for entity in &mut self.entities {
257            if entity.get_kind() == EntityKind::TypedefDecl {
258                let name = entity.get_name().unwrap();
259                if !self.seen.contains(&name) {
260                    let underlying = entity.get_typedef_underlying_type().unwrap();
261                    let display = entity.get_type().unwrap().get_display_name();
262
263                    let typedef = !is_elaborated(underlying) ||
264                        underlying.get_result_type().is_some() ||
265                        is_alias(underlying, &display);
266
267                    if typedef {
268                        self.seen.insert(name.clone());
269                        return Some(Declaration::new(name, entity, None));
270                    }
271                }
272            }
273        }
274        None
275    }
276}
277
278// Unions ________________________________________
279
280/// An iterator over struct declarations.
281#[allow(missing_debug_implementations)]
282pub struct Unions<'tu> {
283    entities: vec::IntoIter<Entity<'tu>>,
284    seen: HashSet<String>,
285}
286
287impl<'tu> Unions<'tu> {
288    //- Constructors -----------------------------
289
290    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Unions<'tu> {
291        Unions { entities, seen: HashSet::new() }
292    }
293}
294
295impl<'tu> Iterator for Unions<'tu> {
296    type Item = Declaration<'tu>;
297
298    fn next(&mut self) -> Option<Declaration<'tu>> {
299        next(&mut self.entities, &mut self.seen, EntityKind::UnionDecl, "union ")
300    }
301}
302
303//================================================
304// Functions
305//================================================
306
307fn is(type_: Type, prefix: &str) -> bool {
308    is_elaborated(type_) && type_.get_display_name().starts_with(prefix)
309}
310
311fn is_alias(type_: Type, name: &str) -> bool {
312    for prefix in &["enum ", "struct ", "union "] {
313        let display = type_.get_display_name();
314
315        if display.starts_with(prefix) && &display[prefix.len()..] != name {
316            return true;
317        }
318    }
319
320    false
321}
322
323fn is_elaborated(type_: Type) -> bool {
324    type_.is_elaborated().unwrap_or(type_.get_kind() == TypeKind::Unexposed)
325}
326
327fn next<'tu>(
328    entities: &mut vec::IntoIter<Entity<'tu>>,
329    seen: &mut HashSet<String>,
330    kind: EntityKind,
331    prefix: &str,
332) -> Option<Declaration<'tu>> {
333    for entity in entities {
334        if entity.get_kind() == kind {
335            if let Some(name) = entity.get_name() {
336                if !seen.contains(&name) {
337                    seen.insert(name);
338                    if entity.get_child(0).is_some() {
339                        return Some(Declaration::new(entity.get_name().unwrap(), entity, None));
340                    }
341                }
342            }
343        } else if entity.get_kind() == EntityKind::TypedefDecl {
344            let underlying = entity.get_typedef_underlying_type().unwrap();
345            let name = entity.get_name().unwrap();
346
347            if is(underlying, prefix) && !seen.contains(&name) {
348                let declaration = underlying.get_declaration().unwrap();
349
350                let complete = declaration.get_type().map_or(false, |t| t.get_sizeof().is_ok());
351                let anonymous = declaration.get_display_name().is_none();
352                let same = entity.get_display_name() == declaration.get_display_name();
353
354                seen.insert(name);
355                if complete && (anonymous || same) {
356                    let name = entity.get_name().unwrap();
357                    return Some(Declaration::new(name, declaration, Some(entity)));
358                }
359            }
360        }
361    }
362    None
363}
364
365/// Returns an iterator over the simple preprocessor definitions in the supplied entities.
366///
367/// Simple preprocessor definitions are those that consist only of a single integer or floating
368/// point literal, optionally negated.
369///
370/// If a preprocessor definition is encountered multiple times, only the first instance is included.
371pub fn find_definitions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Definitions<'tu> {
372    Definitions::new(entities.into().into_iter())
373}
374
375/// Returns an iterator over the enums in the supplied entities.
376///
377/// If an enum is encountered multiple times, only the first instance is included.
378pub fn find_enums<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Enums<'tu> {
379    Enums::new(entities.into().into_iter())
380}
381
382/// Returns an iterator over the functions in the supplied entities.
383///
384/// If a function is encountered multiple times, only the first instance is included.
385pub fn find_functions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Functions<'tu> {
386    Functions::new(entities.into().into_iter())
387}
388
389/// Returns an iterator over the structs in the supplied entities.
390///
391/// If a struct is encountered multiple times, only the first instance is included.
392pub fn find_structs<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Structs<'tu> {
393    Structs::new(entities.into().into_iter())
394}
395
396/// Returns an iterator over the typedefs in the supplied entities.
397///
398/// If a typedef is encountered multiple times, only the first instance is included.
399pub fn find_typedefs<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Typedefs<'tu> {
400    Typedefs::new(entities.into().into_iter())
401}
402
403/// Returns an iterator over the unions in the supplied entities.
404///
405/// If a union is encountered multiple times, only the first instance is included.
406pub fn find_unions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Unions<'tu> {
407    Unions::new(entities.into().into_iter())
408}