|
1 | 1 | //! Contains infrastructure for configuring the compiler, including parsing
|
2 | 2 | //! command-line options.
|
3 | 3 |
|
| 4 | +// ignore-tidy-filelength |
| 5 | + |
4 | 6 | use crate::lint;
|
5 | 7 | use crate::middle::cstore;
|
6 | 8 | use crate::session::{early_error, early_warn, Session};
|
7 | 9 | use crate::session::search_paths::SearchPath;
|
| 10 | +use crate::hir::map as hir_map; |
8 | 11 |
|
9 | 12 | use rustc_data_structures::fx::FxHashSet;
|
10 | 13 |
|
@@ -440,6 +443,8 @@ top_level_options!(
|
440 | 443 | // `true` if we're emitting JSON blobs about each artifact produced
|
441 | 444 | // by the compiler.
|
442 | 445 | json_artifact_notifications: bool [TRACKED],
|
| 446 | + |
| 447 | + pretty: Option<(PpMode, Option<UserIdentifiedItem>)> [UNTRACKED], |
443 | 448 | }
|
444 | 449 | );
|
445 | 450 |
|
@@ -621,6 +626,7 @@ impl Default for Options {
|
621 | 626 | remap_path_prefix: Vec::new(),
|
622 | 627 | edition: DEFAULT_EDITION,
|
623 | 628 | json_artifact_notifications: false,
|
| 629 | + pretty: None, |
624 | 630 | }
|
625 | 631 | }
|
626 | 632 | }
|
@@ -2516,6 +2522,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
2516 | 2522 |
|
2517 | 2523 | let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
|
2518 | 2524 |
|
| 2525 | + let pretty = parse_pretty(matches, &debugging_opts, error_format); |
| 2526 | + |
2519 | 2527 | Options {
|
2520 | 2528 | crate_types,
|
2521 | 2529 | optimize: opt_level,
|
@@ -2546,6 +2554,73 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
2546 | 2554 | remap_path_prefix,
|
2547 | 2555 | edition,
|
2548 | 2556 | json_artifact_notifications,
|
| 2557 | + pretty, |
| 2558 | + } |
| 2559 | +} |
| 2560 | + |
| 2561 | +fn parse_pretty( |
| 2562 | + matches: &getopts::Matches, |
| 2563 | + debugging_opts: &DebuggingOptions, |
| 2564 | + efmt: ErrorOutputType, |
| 2565 | +) -> Option<(PpMode, Option<UserIdentifiedItem>)> { |
| 2566 | + let pretty = if debugging_opts.unstable_options { |
| 2567 | + matches.opt_default("pretty", "normal").map(|a| { |
| 2568 | + // stable pretty-print variants only |
| 2569 | + parse_pretty_inner(efmt, &a, false) |
| 2570 | + }) |
| 2571 | + } else { |
| 2572 | + None |
| 2573 | + }; |
| 2574 | + |
| 2575 | + return if pretty.is_none() { |
| 2576 | + debugging_opts.unpretty.as_ref().map(|a| { |
| 2577 | + // extended with unstable pretty-print variants |
| 2578 | + parse_pretty_inner(efmt, &a, true) |
| 2579 | + }) |
| 2580 | + } else { |
| 2581 | + pretty |
| 2582 | + }; |
| 2583 | + |
| 2584 | + fn parse_pretty_inner( |
| 2585 | + efmt: ErrorOutputType, |
| 2586 | + name: &str, |
| 2587 | + extended: bool, |
| 2588 | + ) -> (PpMode, Option<UserIdentifiedItem>) { |
| 2589 | + use PpMode::*; |
| 2590 | + use PpSourceMode::*; |
| 2591 | + let mut split = name.splitn(2, '='); |
| 2592 | + let first = split.next().unwrap(); |
| 2593 | + let opt_second = split.next(); |
| 2594 | + let first = match (first, extended) { |
| 2595 | + ("normal", _) => PpmSource(PpmNormal), |
| 2596 | + ("identified", _) => PpmSource(PpmIdentified), |
| 2597 | + ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), |
| 2598 | + ("expanded", _) => PpmSource(PpmExpanded), |
| 2599 | + ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), |
| 2600 | + ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), |
| 2601 | + ("hir", true) => PpmHir(PpmNormal), |
| 2602 | + ("hir,identified", true) => PpmHir(PpmIdentified), |
| 2603 | + ("hir,typed", true) => PpmHir(PpmTyped), |
| 2604 | + ("hir-tree", true) => PpmHirTree(PpmNormal), |
| 2605 | + ("mir", true) => PpmMir, |
| 2606 | + ("mir-cfg", true) => PpmMirCFG, |
| 2607 | + _ => { |
| 2608 | + if extended { |
| 2609 | + early_error(efmt, &format!("argument to `unpretty` must be one of `normal`, \ |
| 2610 | + `expanded`, `identified`, `expanded,identified`, \ |
| 2611 | + `expanded,hygiene`, `everybody_loops`, \ |
| 2612 | + `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \ |
| 2613 | + `mir` or `mir-cfg`; got {}", |
| 2614 | + name)); |
| 2615 | + } else { |
| 2616 | + early_error(efmt, &format!("argument to `pretty` must be one of `normal`, \ |
| 2617 | + `expanded`, `identified`, or `expanded,identified`; got {}", |
| 2618 | + name)); |
| 2619 | + } |
| 2620 | + } |
| 2621 | + }; |
| 2622 | + let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>().ok()); |
| 2623 | + (first, opt_second) |
2549 | 2624 | }
|
2550 | 2625 | }
|
2551 | 2626 |
|
@@ -2656,6 +2731,151 @@ impl fmt::Display for CrateType {
|
2656 | 2731 | }
|
2657 | 2732 | }
|
2658 | 2733 |
|
| 2734 | +#[derive(Copy, Clone, PartialEq, Debug)] |
| 2735 | +pub enum PpSourceMode { |
| 2736 | + PpmNormal, |
| 2737 | + PpmEveryBodyLoops, |
| 2738 | + PpmExpanded, |
| 2739 | + PpmIdentified, |
| 2740 | + PpmExpandedIdentified, |
| 2741 | + PpmExpandedHygiene, |
| 2742 | + PpmTyped, |
| 2743 | +} |
| 2744 | + |
| 2745 | +#[derive(Copy, Clone, PartialEq, Debug)] |
| 2746 | +pub enum PpMode { |
| 2747 | + PpmSource(PpSourceMode), |
| 2748 | + PpmHir(PpSourceMode), |
| 2749 | + PpmHirTree(PpSourceMode), |
| 2750 | + PpmMir, |
| 2751 | + PpmMirCFG, |
| 2752 | +} |
| 2753 | + |
| 2754 | +impl PpMode { |
| 2755 | + pub fn needs_ast_map(&self, opt_uii: &Option<UserIdentifiedItem>) -> bool { |
| 2756 | + use PpMode::*; |
| 2757 | + use PpSourceMode::*; |
| 2758 | + match *self { |
| 2759 | + PpmSource(PpmNormal) | |
| 2760 | + PpmSource(PpmEveryBodyLoops) | |
| 2761 | + PpmSource(PpmIdentified) => opt_uii.is_some(), |
| 2762 | + |
| 2763 | + PpmSource(PpmExpanded) | |
| 2764 | + PpmSource(PpmExpandedIdentified) | |
| 2765 | + PpmSource(PpmExpandedHygiene) | |
| 2766 | + PpmHir(_) | |
| 2767 | + PpmHirTree(_) | |
| 2768 | + PpmMir | |
| 2769 | + PpmMirCFG => true, |
| 2770 | + PpmSource(PpmTyped) => panic!("invalid state"), |
| 2771 | + } |
| 2772 | + } |
| 2773 | + |
| 2774 | + pub fn needs_analysis(&self) -> bool { |
| 2775 | + use PpMode::*; |
| 2776 | + match *self { |
| 2777 | + PpmMir | PpmMirCFG => true, |
| 2778 | + _ => false, |
| 2779 | + } |
| 2780 | + } |
| 2781 | +} |
| 2782 | + |
| 2783 | +#[derive(Clone, Debug)] |
| 2784 | +pub enum UserIdentifiedItem { |
| 2785 | + ItemViaNode(ast::NodeId), |
| 2786 | + ItemViaPath(Vec<String>), |
| 2787 | +} |
| 2788 | + |
| 2789 | +impl FromStr for UserIdentifiedItem { |
| 2790 | + type Err = (); |
| 2791 | + fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> { |
| 2792 | + use UserIdentifiedItem::*; |
| 2793 | + Ok(s.parse() |
| 2794 | + .map(ast::NodeId::from_u32) |
| 2795 | + .map(ItemViaNode) |
| 2796 | + .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) |
| 2797 | + } |
| 2798 | +} |
| 2799 | + |
| 2800 | +pub enum NodesMatchingUII<'a> { |
| 2801 | + NodesMatchingDirect(std::option::IntoIter<ast::NodeId>), |
| 2802 | + NodesMatchingSuffix(Box<dyn Iterator<Item = ast::NodeId> + 'a>), |
| 2803 | +} |
| 2804 | + |
| 2805 | +impl<'a> Iterator for NodesMatchingUII<'a> { |
| 2806 | + type Item = ast::NodeId; |
| 2807 | + |
| 2808 | + fn next(&mut self) -> Option<ast::NodeId> { |
| 2809 | + use NodesMatchingUII::*; |
| 2810 | + match self { |
| 2811 | + &mut NodesMatchingDirect(ref mut iter) => iter.next(), |
| 2812 | + &mut NodesMatchingSuffix(ref mut iter) => iter.next(), |
| 2813 | + } |
| 2814 | + } |
| 2815 | + |
| 2816 | + fn size_hint(&self) -> (usize, Option<usize>) { |
| 2817 | + use NodesMatchingUII::*; |
| 2818 | + match self { |
| 2819 | + &NodesMatchingDirect(ref iter) => iter.size_hint(), |
| 2820 | + &NodesMatchingSuffix(ref iter) => iter.size_hint(), |
| 2821 | + } |
| 2822 | + } |
| 2823 | +} |
| 2824 | + |
| 2825 | +impl UserIdentifiedItem { |
| 2826 | + pub fn reconstructed_input(&self) -> String { |
| 2827 | + use UserIdentifiedItem::*; |
| 2828 | + match *self { |
| 2829 | + ItemViaNode(node_id) => node_id.to_string(), |
| 2830 | + ItemViaPath(ref parts) => parts.join("::"), |
| 2831 | + } |
| 2832 | + } |
| 2833 | + |
| 2834 | + pub fn all_matching_node_ids<'a, 'hir>(&'a self, |
| 2835 | + map: &'a hir_map::Map<'hir>) |
| 2836 | + -> NodesMatchingUII<'a> { |
| 2837 | + use UserIdentifiedItem::*; |
| 2838 | + use NodesMatchingUII::*; |
| 2839 | + match *self { |
| 2840 | + ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), |
| 2841 | + ItemViaPath(ref parts) => { |
| 2842 | + NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) |
| 2843 | + } |
| 2844 | + } |
| 2845 | + } |
| 2846 | + |
| 2847 | + pub fn to_one_node_id(self, |
| 2848 | + user_option: &str, |
| 2849 | + sess: &Session, |
| 2850 | + map: &hir_map::Map<'_>) |
| 2851 | + -> ast::NodeId { |
| 2852 | + let fail_because = |is_wrong_because| -> ast::NodeId { |
| 2853 | + let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ |
| 2854 | + {}, which {}", |
| 2855 | + user_option, |
| 2856 | + self.reconstructed_input(), |
| 2857 | + is_wrong_because); |
| 2858 | + sess.fatal(&message) |
| 2859 | + }; |
| 2860 | + |
| 2861 | + let mut saw_node = ast::DUMMY_NODE_ID; |
| 2862 | + let mut seen = 0; |
| 2863 | + for node in self.all_matching_node_ids(map) { |
| 2864 | + saw_node = node; |
| 2865 | + seen += 1; |
| 2866 | + if seen > 1 { |
| 2867 | + fail_because("does not resolve uniquely"); |
| 2868 | + } |
| 2869 | + } |
| 2870 | + if seen == 0 { |
| 2871 | + fail_because("does not resolve to any item"); |
| 2872 | + } |
| 2873 | + |
| 2874 | + assert!(seen == 1); |
| 2875 | + return saw_node; |
| 2876 | + } |
| 2877 | +} |
| 2878 | + |
2659 | 2879 | /// Command-line arguments passed to the compiler have to be incorporated with
|
2660 | 2880 | /// the dependency tracking system for incremental compilation. This module
|
2661 | 2881 | /// provides some utilities to make this more convenient.
|
|
0 commit comments