//! Structural Search Replace
//!
//! Allows searching the AST for code that matches one or more patterns and then replacing that code
//! based on a template.

// Feature: Structural Search and Replace
//
// Search and replace with named wildcards that will match any expression, type, path, pattern or item.
// The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
// A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement.
// Within a macro call, a placeholder will match up until whatever token follows the placeholder.
//
// All paths in both the search pattern and the replacement template must resolve in the context
// in which this command is invoked. Paths in the search pattern will then match the code if they
// resolve to the same item, even if they're written differently. For example if we invoke the
// command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers
// to `foo::Bar` will match.
//
// Paths in the replacement template will be rendered appropriately for the context in which the
// replacement occurs. For example if our replacement template is `foo::Bar` and we match some
// code in the `foo` module, we'll insert just `Bar`.
//
// Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will
// match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`. When a
// placeholder is the receiver of a method call in the search pattern (e.g. `$s.foo()`), but not in
// the replacement template (e.g. `bar($s)`), then *, & and &mut will be added as needed to mirror
// whatever autoderef and autoref was happening implicitly in the matched code.
//
// The scope of the search / replace will be restricted to the current selection if any, otherwise
// it will apply to the whole workspace.
//
// Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`.
//
// Supported constraints:
//
// | Constraint    | Restricts placeholder |
// |---------------|------------------------|
// | kind(literal) | Is a literal (e.g. `42` or `"forty two"`) |
// | not(a)        | Negates the constraint `a` |
//
// Available via the command `rust-analyzer.ssr`.
//
// ```rust
// // Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)]
//
// // BEFORE
// String::from(foo(y + 5, z))
//
// // AFTER
// String::from((y + 5).foo(z))
// ```
//
// | Editor  | Action Name |
// |---------|--------------|
// | VS Code | **rust-analyzer: Structural Search Replace** |
//
// Also available as an assist, by writing a comment containing the structural
// search and replace rule. You will only see the assist if the comment can
// be parsed as a valid structural search and replace rule.
//
// ```rust
// // Place the cursor on the line below to see the assist 💡.
// // foo($a, $b) ==>> ($a).foo($b)
// ```

mod fragments;
mod from_comment;
mod matching;
mod nester;
mod parsing;
mod replacing;
mod resolving;
mod search;
#[macro_use]
mod errors;
#[cfg(test)]
mod tests;

pub use crate::{errors::SsrError, from_comment::ssr_from_comment, matching::Match};

use crate::{errors::bail, matching::MatchFailureReason};
use hir::{FileRange, Semantics};
use ide_db::symbol_index::LocalRoots;
use ide_db::text_edit::TextEdit;
use ide_db::{EditionedFileId, FileId, FxHashMap, RootDatabase, base_db::SourceDatabase};
use resolving::ResolvedRule;
use syntax::{AstNode, SyntaxNode, TextRange, ast};

// A structured search replace rule. Create by calling `parse` on a str.
#[derive(Debug)]
pub struct SsrRule {
    /// A structured pattern that we're searching for.
    pattern: parsing::RawPattern,
    /// What we'll replace it with.
    template: parsing::RawPattern,
    parsed_rules: Vec<parsing::ParsedRule>,
}

#[derive(Debug)]
pub struct SsrPattern {
    parsed_rules: Vec<parsing::ParsedRule>,
}

#[derive(Debug, Default)]
pub struct SsrMatches {
    pub matches: Vec<Match>,
}

/// Searches a crate for pattern matches and possibly replaces them with something else.
pub struct MatchFinder<'db> {
    /// Our source of information about the user's code.
    sema: Semantics<'db, ide_db::RootDatabase>,
    rules: Vec<ResolvedRule<'db>>,
    resolution_scope: resolving::ResolutionScope<'db>,
    restrict_ranges: Vec<ide_db::FileRange>,
}

impl<'db> MatchFinder<'db> {
    /// Constructs a new instance where names will be looked up as if they appeared at
    /// `lookup_context`.
    pub fn in_context(
        db: &'db RootDatabase,
        lookup_context: ide_db::FilePosition,
        mut restrict_ranges: Vec<ide_db::FileRange>,
    ) -> Result<MatchFinder<'db>, SsrError> {
        restrict_ranges.retain(|range| !range.range.is_empty());
        let sema = Semantics::new(db);
        let file_id = sema
            .attach_first_edition(lookup_context.file_id)
            .unwrap_or_else(|| EditionedFileId::current_edition(db, lookup_context.file_id));
        let resolution_scope = resolving::ResolutionScope::new(
            &sema,
            hir::FilePosition { file_id, offset: lookup_context.offset },
        )
        .ok_or_else(|| SsrError("no resolution scope for file".into()))?;
        Ok(MatchFinder { sema, rules: Vec::new(), resolution_scope, restrict_ranges })
    }

    /// Constructs an instance using the start of the first file in `db` as the lookup context.
    pub fn at_first_file(db: &'db ide_db::RootDatabase) -> Result<MatchFinder<'db>, SsrError> {
        if let Some(first_file_id) = LocalRoots::get(db)
            .roots(db)
            .iter()
            .next()
            .and_then(|root| db.source_root(*root).source_root(db).iter().next())
        {
            MatchFinder::in_context(
                db,
                ide_db::FilePosition { file_id: first_file_id, offset: 0.into() },
                vec![],
            )
        } else {
            bail!("No files to search");
        }
    }

    /// Adds a rule to be applied. The order in which rules are added matters. Earlier rules take
    /// precedence. If a node is matched by an earlier rule, then later rules won't be permitted to
    /// match to it.
    pub fn add_rule(&mut self, rule: SsrRule) -> Result<(), SsrError> {
        for parsed_rule in rule.parsed_rules {
            self.rules.push(ResolvedRule::new(
                parsed_rule,
                &self.resolution_scope,
                self.rules.len(),
            )?);
        }
        Ok(())
    }

    /// Finds matches for all added rules and returns edits for all found matches.
    pub fn edits(&self) -> FxHashMap<FileId, TextEdit> {
        let mut matches_by_file = FxHashMap::default();
        for m in self.matches().matches {
            matches_by_file
                .entry(m.range.file_id.file_id(self.sema.db))
                .or_insert_with(SsrMatches::default)
                .matches
                .push(m);
        }
        matches_by_file
            .into_iter()
            .map(|(file_id, matches)| {
                (
                    file_id,
                    replacing::matches_to_edit(
                        self.sema.db,
                        &matches,
                        self.sema.db.file_text(file_id).text(self.sema.db),
                        &self.rules,
                    ),
                )
            })
            .collect()
    }

    /// Adds a search pattern. For use if you intend to only call `find_matches_in_file`. If you
    /// intend to do replacement, use `add_rule` instead.
    pub fn add_search_pattern(&mut self, pattern: SsrPattern) -> Result<(), SsrError> {
        for parsed_rule in pattern.parsed_rules {
            self.rules.push(ResolvedRule::new(
                parsed_rule,
                &self.resolution_scope,
                self.rules.len(),
            )?);
        }
        Ok(())
    }

    /// Returns matches for all added rules.
    pub fn matches(&self) -> SsrMatches {
        let mut matches = Vec::new();
        let mut usage_cache = search::UsageCache::default();
        for rule in &self.rules {
            self.find_matches_for_rule(rule, &mut usage_cache, &mut matches);
        }
        nester::nest_and_remove_collisions(matches, &self.sema)
    }

    /// Finds all nodes in `file_id` whose text is exactly equal to `snippet` and attempts to match
    /// them, while recording reasons why they don't match. This API is useful for command
    /// line-based debugging where providing a range is difficult.
    pub fn debug_where_text_equal(
        &self,
        file_id: EditionedFileId,
        snippet: &str,
    ) -> Vec<MatchDebugInfo> {
        let file = self.sema.parse(file_id);
        let mut res = Vec::new();
        let file_text = self.sema.db.file_text(file_id.file_id(self.sema.db)).text(self.sema.db);
        let mut remaining_text = &**file_text;
        let mut base = 0;
        let len = snippet.len() as u32;
        while let Some(offset) = remaining_text.find(snippet) {
            let start = base + offset as u32;
            let end = start + len;
            self.output_debug_for_nodes_at_range(
                file.syntax(),
                FileRange { file_id, range: TextRange::new(start.into(), end.into()) },
                &None,
                &mut res,
            );
            remaining_text = &remaining_text[offset + snippet.len()..];
            base = end;
        }
        res
    }

    fn output_debug_for_nodes_at_range(
        &self,
        node: &SyntaxNode,
        range: FileRange,
        restrict_range: &Option<FileRange>,
        out: &mut Vec<MatchDebugInfo>,
    ) {
        for node in node.children() {
            let node_range = self.sema.original_range(&node);
            if node_range.file_id != range.file_id || !node_range.range.contains_range(range.range)
            {
                continue;
            }
            if node_range.range == range.range {
                for rule in &self.rules {
                    // For now we ignore rules that have a different kind than our node, otherwise
                    // we get lots of noise. If at some point we add support for restricting rules
                    // to a particular kind of thing (e.g. only match type references), then we can
                    // relax this. We special-case expressions, since function calls can match
                    // method calls.
                    if rule.pattern.node.kind() != node.kind()
                        && !(ast::Expr::can_cast(rule.pattern.node.kind())
                            && ast::Expr::can_cast(node.kind()))
                    {
                        continue;
                    }
                    out.push(MatchDebugInfo {
                        matched: matching::get_match(true, rule, &node, restrict_range, &self.sema)
                            .map_err(|e| MatchFailureReason {
                                reason: e.reason.unwrap_or_else(|| {
                                    "Match failed, but no reason was given".to_owned()
                                }),
                            }),
                        pattern: rule.pattern.node.clone(),
                        node: node.clone(),
                    });
                }
            } else if let Some(macro_call) = ast::MacroCall::cast(node.clone())
                && let Some(expanded) = self.sema.expand_macro_call(&macro_call)
                && let Some(tt) = macro_call.token_tree()
            {
                self.output_debug_for_nodes_at_range(
                    &expanded.value,
                    range,
                    &Some(self.sema.original_range(tt.syntax())),
                    out,
                );
            }
            self.output_debug_for_nodes_at_range(&node, range, restrict_range, out);
        }
    }
}

pub struct MatchDebugInfo {
    node: SyntaxNode,
    /// Our search pattern parsed as an expression or item, etc
    pattern: SyntaxNode,
    matched: Result<Match, MatchFailureReason>,
}

impl std::fmt::Debug for MatchDebugInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match &self.matched {
            Ok(_) => writeln!(f, "Node matched")?,
            Err(reason) => writeln!(f, "Node failed to match because: {}", reason.reason)?,
        }
        writeln!(
            f,
            "============ AST ===========\n\
            {:#?}",
            self.node
        )?;
        writeln!(f, "========= PATTERN ==========")?;
        writeln!(f, "{:#?}", self.pattern)?;
        writeln!(f, "============================")?;
        Ok(())
    }
}

impl SsrMatches {
    /// Returns `self` with any nested matches removed and made into top-level matches.
    pub fn flattened(self) -> SsrMatches {
        let mut out = SsrMatches::default();
        self.flatten_into(&mut out);
        out
    }

    fn flatten_into(self, out: &mut SsrMatches) {
        for mut m in self.matches {
            for p in m.placeholder_values.values_mut() {
                std::mem::take(&mut p.inner_matches).flatten_into(out);
            }
            out.matches.push(m);
        }
    }
}

impl Match {
    pub fn matched_text(&self) -> String {
        self.matched_node.text().to_string()
    }
}

impl std::error::Error for SsrError {}

#[cfg(test)]
impl MatchDebugInfo {
    pub fn match_failure_reason(&self) -> Option<&str> {
        self.matched.as_ref().err().map(|r| r.reason.as_str())
    }
}
