Skip to main content

weavatrix_parse/hcl/
mod.rs

1//! Structural extraction for Terraform and HCL.
2//!
3//! Infrastructure is a dependency graph that no other extractor here can see.
4//! A `module` block names another directory of configuration; a `source` in
5//! `required_providers` names a registry package; and every `var.x`,
6//! `module.m.out` and `aws_s3_bucket.b.id` is a reference from one declared
7//! object to another. Those are the same edges a code graph carries, drawn
8//! over a part of the repository that has been invisible until now.
9
10use crate::facts::{Declaration, DeclarationKind, Facts, Import, Reference, ReferenceKind, Span};
11use crate::syntax::Language;
12use crate::token::{Mode, Token, TokenKind, Tokenizer};
13
14/// Extracts structural facts from one Terraform or HCL file.
15#[must_use]
16pub fn extract(source: &str) -> Facts {
17    let tokens = Tokenizer::new(source, Language::Terraform)
18        .mode(Mode::Lite)
19        .collect::<Vec<_>>();
20    let mut state = Extractor {
21        source,
22        tokens: &tokens,
23        facts: Facts::default(),
24        block: Vec::new(),
25        depth: 0,
26    };
27    state.run();
28    state.facts
29}
30
31/// Block types whose labels name the object they declare.
32const DECLARING: &[(&str, DeclarationKind)] = &[
33    ("resource", DeclarationKind::Resource),
34    ("data", DeclarationKind::Resource),
35    ("module", DeclarationKind::Module),
36    ("variable", DeclarationKind::Variable),
37    ("output", DeclarationKind::Resource),
38    ("provider", DeclarationKind::Module),
39    ("locals", DeclarationKind::Constant),
40];
41
42/// Prefixes that introduce a reference to another declared object.
43const REFERENCE_ROOTS: &[&str] = &["var", "module", "data", "local", "each"];
44
45struct Extractor<'source, 'tokens> {
46    source: &'source str,
47    tokens: &'tokens [Token],
48    facts: Facts,
49    /// Names of the enclosing blocks, innermost last.
50    block: Vec<String>,
51    depth: i32,
52}
53
54mod extractor;
55
56#[cfg(test)]
57mod tests;