//! Contains information about "passes", used to modify crate information during the documentation
//! process.

use rustc_middle::ty::TyCtxt;
use rustc_span::{InnerSpan, Span, DUMMY_SP};
use std::ops::Range;

use self::Condition::*;
use crate::clean::{self, DocFragmentKind};
use crate::core::DocContext;

mod stripper;
crate use stripper::*;

mod bare_urls;
crate use self::bare_urls::CHECK_BARE_URLS;

mod strip_hidden;
crate use self::strip_hidden::STRIP_HIDDEN;

mod strip_private;
crate use self::strip_private::STRIP_PRIVATE;

mod strip_priv_imports;
crate use self::strip_priv_imports::STRIP_PRIV_IMPORTS;

mod unindent_comments;
crate use self::unindent_comments::UNINDENT_COMMENTS;

mod propagate_doc_cfg;
crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;

crate mod collect_intra_doc_links;
crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;

mod doc_test_lints;
crate use self::doc_test_lints::CHECK_PRIVATE_ITEMS_DOC_TESTS;

mod collect_trait_impls;
crate use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;

mod check_code_block_syntax;
crate use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;

mod calculate_doc_coverage;
crate use self::calculate_doc_coverage::CALCULATE_DOC_COVERAGE;

mod html_tags;
crate use self::html_tags::CHECK_INVALID_HTML_TAGS;

/// A single pass over the cleaned documentation.
///
/// Runs in the compiler context, so it has access to types and traits and the like.
#[derive(Copy, Clone)]
crate struct Pass {
    crate name: &'static str,
    crate run: fn(clean::Crate, &mut DocContext<'_>) -> clean::Crate,
    crate description: &'static str,
}

/// In a list of passes, a pass that may or may not need to be run depending on options.
#[derive(Copy, Clone)]
crate struct ConditionalPass {
    crate pass: Pass,
    crate condition: Condition,
}

/// How to decide whether to run a conditional pass.
#[derive(Copy, Clone)]
crate enum Condition {
    Always,
    /// When `--document-private-items` is passed.
    WhenDocumentPrivate,
    /// When `--document-private-items` is not passed.
    WhenNotDocumentPrivate,
    /// When `--document-hidden-items` is not passed.
    WhenNotDocumentHidden,
}

/// The full list of passes.
crate const PASSES: &[Pass] = &[
    CHECK_PRIVATE_ITEMS_DOC_TESTS,
    STRIP_HIDDEN,
    UNINDENT_COMMENTS,
    STRIP_PRIVATE,
    STRIP_PRIV_IMPORTS,
    PROPAGATE_DOC_CFG,
    COLLECT_INTRA_DOC_LINKS,
    CHECK_CODE_BLOCK_SYNTAX,
    COLLECT_TRAIT_IMPLS,
    CALCULATE_DOC_COVERAGE,
    CHECK_INVALID_HTML_TAGS,
    CHECK_BARE_URLS,
];

/// The list of passes run by default.
crate const DEFAULT_PASSES: &[ConditionalPass] = &[
    ConditionalPass::always(COLLECT_TRAIT_IMPLS),
    ConditionalPass::always(UNINDENT_COMMENTS),
    ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS),
    ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
    ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
    ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate),
    ConditionalPass::always(COLLECT_INTRA_DOC_LINKS),
    ConditionalPass::always(CHECK_CODE_BLOCK_SYNTAX),
    ConditionalPass::always(CHECK_INVALID_HTML_TAGS),
    ConditionalPass::always(PROPAGATE_DOC_CFG),
    ConditionalPass::always(CHECK_BARE_URLS),
];

/// The list of default passes run when `--doc-coverage` is passed to rustdoc.
crate const COVERAGE_PASSES: &[ConditionalPass] = &[
    ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
    ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
    ConditionalPass::always(CALCULATE_DOC_COVERAGE),
];

impl ConditionalPass {
    crate const fn always(pass: Pass) -> Self {
        Self::new(pass, Always)
    }

    crate const fn new(pass: Pass, condition: Condition) -> Self {
        ConditionalPass { pass, condition }
    }
}

/// A shorthand way to refer to which set of passes to use, based on the presence of
/// `--no-defaults` and `--show-coverage`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
crate enum DefaultPassOption {
    Default,
    Coverage,
    None,
}

/// Returns the given default set of passes.
crate fn defaults(default_set: DefaultPassOption) -> &'static [ConditionalPass] {
    match default_set {
        DefaultPassOption::Default => DEFAULT_PASSES,
        DefaultPassOption::Coverage => COVERAGE_PASSES,
        DefaultPassOption::None => &[],
    }
}

/// If the given name matches a known pass, returns its information.
crate fn find_pass(pass_name: &str) -> Option<Pass> {
    PASSES.iter().find(|p| p.name == pass_name).copied()
}

/// Returns a span encompassing all the given attributes.
crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
    if attrs.doc_strings.is_empty() {
        return None;
    }
    let start = attrs.doc_strings[0].span;
    if start == DUMMY_SP {
        return None;
    }
    let end = attrs.doc_strings.last().expect("no doc strings provided").span;
    Some(start.to(end))
}

/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
///
/// This method will return `None` if we cannot construct a span from the source map or if the
/// attributes are not all sugared doc comments. It's difficult to calculate the correct span in
/// that case due to escaping and other source features.
crate fn source_span_for_markdown_range(
    tcx: TyCtxt<'_>,
    markdown: &str,
    md_range: &Range<usize>,
    attrs: &clean::Attributes,
) -> Option<Span> {
    let is_all_sugared_doc =
        attrs.doc_strings.iter().all(|frag| frag.kind == DocFragmentKind::SugaredDoc);

    if !is_all_sugared_doc {
        return None;
    }

    let snippet = tcx.sess.source_map().span_to_snippet(span_of_attrs(attrs)?).ok()?;

    let starting_line = markdown[..md_range.start].matches('\n').count();
    let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count();

    // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we treat
    // CRLF and LF line endings the same way.
    let mut src_lines = snippet.split_terminator('\n');
    let md_lines = markdown.split_terminator('\n');

    // The number of bytes from the source span to the markdown span that are not part
    // of the markdown, like comment markers.
    let mut start_bytes = 0;
    let mut end_bytes = 0;

    'outer: for (line_no, md_line) in md_lines.enumerate() {
        loop {
            let source_line = src_lines.next().expect("could not find markdown in source");
            match source_line.find(md_line) {
                Some(offset) => {
                    if line_no == starting_line {
                        start_bytes += offset;

                        if starting_line == ending_line {
                            break 'outer;
                        }
                    } else if line_no == ending_line {
                        end_bytes += offset;
                        break 'outer;
                    } else if line_no < starting_line {
                        start_bytes += source_line.len() - md_line.len();
                    } else {
                        end_bytes += source_line.len() - md_line.len();
                    }
                    break;
                }
                None => {
                    // Since this is a source line that doesn't include a markdown line,
                    // we have to count the newline that we split from earlier.
                    if line_no <= starting_line {
                        start_bytes += source_line.len() + 1;
                    } else {
                        end_bytes += source_line.len() + 1;
                    }
                }
            }
        }
    }

    Some(span_of_attrs(attrs)?.from_inner(InnerSpan::new(
        md_range.start + start_bytes,
        md_range.end + start_bytes + end_bytes,
    )))
}
