forked from
gleam.run/gleam
⭐️ A friendly language for building type-safe, scalable systems!
3.0 kB
92 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2023 The Gleam contributors
3
4use std::rc::Rc;
5
6use gleam_core::{
7 Error, Result, Warning,
8 analyse::TargetSupport,
9 build::{Codegen, Compile, Mode, Options},
10 error::{FileIoAction, FileKind},
11 paths::ProjectPaths,
12 type_,
13 warning::VectorWarningEmitterIO,
14};
15use hexpm::version::Version;
16
17use crate::{build, cli};
18
19pub fn run(paths: &ProjectPaths) -> Result<()> {
20 // When running gleam fix we want all the compilation warnings to be hidden,
21 // at the same time we need to access those to apply the fixes: so we
22 // accumulate those into a vector.
23 let warnings = Rc::new(VectorWarningEmitterIO::new());
24 let _built = build::main_with_warnings(
25 paths,
26 Options {
27 root_target_support: TargetSupport::Enforced,
28 warnings_as_errors: false,
29 codegen: Codegen::DepsOnly,
30 compile: Compile::All,
31 mode: Mode::Dev,
32 target: None,
33 no_print_progress: false,
34 },
35 build::download_dependencies(paths, cli::Reporter::new())?,
36 warnings.clone(),
37 )?;
38 let warnings = warnings.take();
39
40 fix_minimum_required_version(paths, warnings)?;
41
42 println!("Done!");
43 Ok(())
44}
45
46fn fix_minimum_required_version(paths: &ProjectPaths, warnings: Vec<Warning>) -> Result<()> {
47 let Some(minimum_required_version) = minimum_required_version_from_warnings(warnings) else {
48 return Ok(());
49 };
50
51 // Set the version requirement in gleam.toml
52 let root_config = paths.root_config();
53 let mut toml = crate::fs::read(&root_config)?
54 .parse::<toml_edit::DocumentMut>()
55 .map_err(|e| Error::FileIo {
56 kind: FileKind::File,
57 action: FileIoAction::Parse,
58 path: root_config.to_path_buf(),
59 err: Some(e.to_string()),
60 })?;
61
62 #[allow(clippy::indexing_slicing)]
63 {
64 toml["gleam"] = toml_edit::value(format!(">= {minimum_required_version}"));
65 }
66
67 // Write the updated config
68 crate::fs::write(root_config.as_path(), &toml.to_string())?;
69
70 println!("- Set required Gleam version to \">= {minimum_required_version}\"");
71 Ok(())
72}
73
74/// Returns the highest minimum required version among all warnings requiring a
75/// specific Gleam version that is not allowed by the `gleam` version contraint
76/// in the `gleam.toml`.
77fn minimum_required_version_from_warnings(warnings: Vec<Warning>) -> Option<Version> {
78 warnings
79 .iter()
80 .filter_map(|warning| match warning {
81 Warning::Type { warning, .. } => match warning.as_ref() {
82 type_::Warning::FeatureRequiresHigherGleamVersion {
83 minimum_required_version,
84 ..
85 } => Some(minimum_required_version),
86 _ => None,
87 },
88 _ => None,
89 })
90 .reduce(std::cmp::max)
91 .cloned()
92}