Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file cmd__lint.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111(*********************************************************************************)(* Dunolint - A tool to lint and help manage files in dune projects *)(* Copyright (C) 2024-2025 Mathieu Barbin <mathieu.barbin@gmail.com> *)(* *)(* This file is part of Dunolint. *)(* *)(* Dunolint is free software; you can redistribute it and/or modify it *)(* under the terms of the GNU Lesser General Public License as published by *)(* the Free Software Foundation either version 3 of the License, or any later *)(* version, with the LGPL-3.0 Linking Exception. *)(* *)(* Dunolint is distributed in the hope that it will be useful, but WITHOUT *)(* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *)(* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *)(* and the file `NOTICE.md` at the root of this repository for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* and the LGPL-3.0 Linking Exception along with this library. If not, see *)(* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively. *)(*********************************************************************************)letmain=Command.make~summary:"Lint project."~readme:(fun()->"This command lints files in a dune project starting from the workspace root.\n\n\
Dunolint will first locate the workspace root by searching for \
$(b,dune-workspace) or $(b,dune-project) files in the current directory and its \
ancestors (using the same logic as Dune), then change to that directory before \
performing linting operations. The workspace root can be overridden using the \
$(b,--root) flag.\n\n\
$(b,Config Autoloading:) By default, dunolint will automatically discover and \
load $(b,dunolint) config files found in the workspace root and any \
subdirectories during traversal. Configs are accumulated from root down to each \
linted file's directory.\n\n\
$(b,Config Accumulation and Precedence:) When multiple configs are loaded (e.g., \
from root and subdirectories), $(b,all) rules from $(b,all) configs are applied \
in sequence. Rules from configs deeper in the tree are applied last and take \
precedence when modifying the same fields.\n\n\
$(b,Config Autoloading and Manual Override:) Config autoloading is $(b,disabled) \
when either $(b,--config) or $(b,--enforce) flags are supplied. The $(b,--config) \
flag specifies an explicit config file to use instead of autoloading. The \
$(b,--enforce) flag adds specific conditions to enforce. Both flags can be used \
together, and both treat paths as if resolved from the workspace root. Note that \
default skip paths are $(b,always) applied regardless of which flags are used.\n\n\
Use $(b,--below) to limit linting to a specific subdirectory. When using \
$(b,--below), configs from ancestor directories (including the workspace root) \
are still loaded and applied.")(letopenCommand.Stdinlet+running_mode=Dunolint_engine.Running_mode.argand+()=Log_cli.set_config()and+config=Arg.named_opt["config"]Param.file~doc:"Path to dunolint config file. When specified, config autoloading is disabled \
and only this config is used. The config is evaluated as if it were located \
at the workspace root (important for path resolution). This flag is \
primarily meant for backward compatibility and quick testing; new code and \
persistent setups should use dunolint config files directly."and+below=Common_helpers.below~doc:"Lint only below this path."and+enforce=Arg.named_multi["enforce"](Common_helpers.sexpable_param(moduleDunolint.Condition))~docv:"COND"~doc:"Add condition to enforce. Can be specified multiple times. $(b,Deprecated): \
This flag is primarily for backward compatibility and testing. For \
persistent rules, add them to a dunolint config file. For one-off \
transitions and quick edits, future dedicated tooling is planned. This flag \
can be used alone or combined with $(b,--config). When combined, the config \
file is applied first, then enforce rules are applied last.">>|List.map~f:(funcondition->`enforcecondition)and+root=Common_helpers.rootinletcwd=Unix.getcwd()|>Absolute_path.vinletworkspace_root=Workspace_root.find_exn~default_is_cwd:false~specified_by_user:rootinletbelow=Option.mapbelow~f:(funbelow->Common_helpers.relativize~workspace_root~cwd~path:below)inletconfig=Option.mapconfig~f:(funconfig->Common_helpers.relativize~workspace_root~cwd~path:(Fpath.vconfig)|>Relative_path.to_string)inWorkspace_root.chdirworkspace_root~level:Warning;letroot_configs=List.concat[[Common_helpers.default_skip_paths_config()];(matchconfigwith|None->[]|Someconfig_path->[Dunolinter.Config_handler.load_config_exn~filename:config_path]);(matchCommon_helpers.enforce_rules_config~rules:enforcewith|None->[]|Someconfig->[config])]inDunolint_engine.run~root_configs~running_mode@@fundunolint_engine->Dunolint_engine.visitdunolint_engine~autoload_config:(Option.is_noneconfig&&List.is_emptyenforce)?below~f:(fun~context~parent_dir~subdirectories:_~files->Linter.visit_directory~dunolint_engine~context~parent_dir~files));;