diff --git a/src/dune_config/config.ml b/src/dune_config/config.ml index 1ec1ef3313c..f5fbc03ac66 100644 --- a/src/dune_config/config.ml +++ b/src/dune_config/config.ml @@ -86,6 +86,7 @@ let make ~name ~of_string ~default = ;; let make_toggle ~name ~default = make ~name ~default ~of_string:Toggle.of_string + let global_lock = make ~name:"global_lock" ~of_string:Toggle.of_string ~default:`Enabled let cutoffs_that_reduce_concurrency_in_watch_mode = @@ -147,3 +148,7 @@ let threaded_console_frames_per_second = | None -> Error (sprintf "could not parse %S as an integer" x)) ~default:`Default ;; + +let typo_warnings = + make ~name:"typo_warnings" ~of_string:Toggle.of_string ~default:`Enabled +;; \ No newline at end of file diff --git a/src/dune_config/config.mli b/src/dune_config/config.mli index 4c1d3944aaa..62495ca990c 100644 --- a/src/dune_config/config.mli +++ b/src/dune_config/config.mli @@ -60,10 +60,13 @@ val threaded_console : Toggle.t t (** The number of frames per second for the threaded console. *) val threaded_console_frames_per_second : [ `Default | `Custom of int ] t +(** Control whether to show warnings for common typos in package dependencies *) +val typo_warnings : Toggle.t t + (** Before any configuration value is accessed, this function must be called with all the configuration values from the relevant config file ([dune-workspace], or [dune-config]). Note that environment variables take precedence over the values passed here for easy overriding. *) -val init : (Loc.t * string) String.Map.t -> unit +val init : (Loc.t * string) String.Map.t -> unit \ No newline at end of file diff --git a/src/dune_lang/package_dependency.ml b/src/dune_lang/package_dependency.ml index 99de042b6e5..89f90acd560 100644 --- a/src/dune_lang/package_dependency.ml +++ b/src/dune_lang/package_dependency.ml @@ -28,57 +28,62 @@ module Well_formed_name = struct module TT = Dune_util.Stringlike.Make (T) let decode = - let open Decoder in + let open Dune_sexp.Decoder in TT.decode >>| T.to_package_name ;; end let encode { name; constraint_ } = - let open Encoder in + let open Dune_sexp.Encoder in match constraint_ with | None -> Package_name.encode name | Some c -> pair Package_name.encode Package_constraint.encode (name, c) ;; (* Check for common typos in package dependency constraints *) -let check_for_typo ~loc { name; constraint_ } = - let open Package_constraint in - match constraint_ with - | Some (Uop (Relop.Eq, Value.String_literal "version")) -> - let message = - User_message.make - ~loc - [ Pp.textf - "Possible typo in constraint for dependency %S: '(= version)' might be a \ - mistake." - (Package_name.to_string name) - ] - ~hints: - [ Pp.textf - "Did you mean to use the `:version` variable instead? Example: (depends \ - (%s (= :version)))" - (Package_name.to_string name) - ] - in - Some message - | Some (Bvar var) when String.equal (Package_variable_name.to_string var) "with_test" -> - let message = - User_message.make - ~loc - [ Pp.textf - "Possible typo in constraint for dependency %S: ':with_test' might be a \ - mistake." - (Package_name.to_string name) - ] - ~hints: - [ Pp.textf - "Did you mean to use ':with-test' instead? Example: (depends (%s \ - :with-test))" - (Package_name.to_string name) - ] - in - Some message - | _ -> None +let dependency_constraint_variable_typo_warnings ~loc { name; constraint_ } = + match Dune_config.Config.(get typo_warnings) with + | `Enabled -> + (match constraint_ with + | Some + (Package_constraint.Uop + (Relop.Eq, Package_constraint.Value.String_literal "version")) -> + let message = + User_message.make + ~loc + [ Pp.textf + "Possible typo in constraint for dependency %S: '(= version)' might be a \ + mistake." + (Package_name.to_string name) + ] + ~hints: + [ Pp.textf + "Did you mean to use the `:version` variable instead? Example: (depends \ + (%s (= :version)))" + (Package_name.to_string name) + ] + in + Some message + | Some (Package_constraint.Bvar var) + when String.equal (Package_variable_name.to_string var) "with_test" -> + let message = + User_message.make + ~loc + [ Pp.textf + "Possible typo in constraint for dependency %S: ':with_test' might be a \ + mistake." + (Package_name.to_string name) + ] + ~hints: + [ Pp.textf + "Did you mean to use ':with-test' instead? Example: (depends (%s \ + :with-test))" + (Package_name.to_string name) + ] + in + Some message + | _ -> None) + | `Disabled -> None ;; let decode = @@ -88,8 +93,7 @@ let decode = and+ name = Package_name.decode and+ expr = Package_constraint.decode in let result = { name; constraint_ = Some expr } in - (* Check for typos and emit warnings *) - (match check_for_typo ~loc result with + (match dependency_constraint_variable_typo_warnings ~loc result with | Some msg -> User_warning.emit_message msg | None -> ()); result diff --git a/test/blackbox-tests/test-cases/disabled_warning.t b/test/blackbox-tests/test-cases/disabled_warning.t new file mode 100644 index 00000000000..0dddddab58d --- /dev/null +++ b/test/blackbox-tests/test-cases/disabled_warning.t @@ -0,0 +1,60 @@ +Test detection and disabling of common typos in package dependencies + +First, create a dune-project file with typos to see warnings with default settings (warnings enabled) + $ cat > dune-project < (lang dune 3.11) + > (package + > (name foo) + > (allow_empty) + > (depends + > (bar (= version)) ; Should detect typo and suggest :version + > (baz :with_test) ; Should detect typo and suggest :with-test + > qux)) + > EOF + + $ dune pkg lock + File "dune-project", line 6, characters 3-20: + 6 | (bar (= version)) ; Should detect typo and suggest :version + ^^^^^^^^^^^^^^^^^ + Warning: Possible typo in constraint for dependency "bar": '(= version)' might be a mistake. + Hint: Did you mean to use the `:version` variable instead? Example: (depends (bar (= :version))) + File "dune-project", line 7, characters 3-19: + 7 | (baz :with_test) ; Should detect typo and suggest :with-test + ^^^^^^^^^^^^^^^^ + Warning: Possible typo in constraint for dependency "baz": ':with_test' might be a mistake. + Hint: Did you mean to use ':with-test' instead? Example: (depends (baz :with-test)) + +Now demonstrate that fixed dependencies don't cause warnings + $ cat > fixed-dune-project < (lang dune 3.11) + > (package + > (name foo) + > (allow_empty) + > (depends + > (bar (= :version)) ; Fixed version + > (baz :with-test) ; Fixed with-test + > qux)) + > EOF + + $ dune pkg lock --project-file=fixed-dune-project + +Now test that we can disable warnings via the environment variable + $ DUNE_CONFIG__TYPO_WARNINGS=disabled dune pkg lock + + $ # Create clean directory for next test + $ mkdir disable_test + $ cd disable_test + + $ cat > dune-project < (lang dune 3.11) + > (package + > (name foo) + > (allow_empty) + > (depends + > (bar (= version)) ; Should NOT show warning with typo_warnings disabled + > (baz :with_test) ; Should NOT show warning with typo_warnings disabled + > qux)) + > EOF + + $ DUNE_CONFIG__TYPO_WARNINGS=disabled dune pkg lock + $ # No warnings should be produced when the feature is disabled \ No newline at end of file