<commit_before>/// This list represents the default file types that ripgrep ships with. In
/// general, any file format is fair game, although it should generally be
/// limited to reasonably popular open formats. For other cases, you can add
/// types to each invocation of ripgrep with the '--type-add' flag.
///
/// If you would like to add or improve this list, please file a PR:
/// <https://github.com/BurntSushi/ripgrep>.
///
/// Please try to keep this list sorted lexicographically and wrapped to 79
/// columns (inclusive).
#[rustfmt::skip]
pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
    ("agda", &["*.agda", "*.lagda"]),
    ("aidl", &["*.aidl"]),
    ("amake", &["*.mk", "*.bp"]),
    ("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
    ("asm", &["*.asm", "*.s", "*.S"]),
    ("asp", &[
        "*.aspx", "*.aspx.cs", "*.aspx.vb", "*.ascx", "*.ascx.cs",
        "*.ascx.vb", "*.asp"
    ]),
    ("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]),
    ("avro", &["*.avdl", "*.avpr", "*.avsc"]),
    ("awk", &["*.awk"]),
    ("bazel", &[
        "*.bazel", "*.bzl", "*.BUILD", "*.bazelrc", "BUILD", "MODULE.bazel",
        "WORKSPACE", "WORKSPACE.bazel",
    ]),
    ("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
    ("brotli", &["*.br"]),
    ("buildstream", &["*.bst"]),
    ("bzip2", &["*.bz2", "*.tbz2"]),
    ("c", &["*.[chH]", "*.[chH].in", "*.cats"]),
    ("cabal", &["*.cabal"]),
    ("candid", &["*.did"]),
    ("carp", &["*.carp"]),
    ("cbor", &["*.cbor"]),
    ("ceylon", &["*.ceylon"]),
    ("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
    ("cmake", &["*.cmake", "CMakeLists.txt"]),
    ("coffeescript", &["*.coffee"]),
    ("config", &["*.cfg", "*.conf", "*.config", "*.ini"]),
    ("coq", &["*.v"]),
    ("cpp", &[
        "*.[ChH]", "*.cc", "*.[ch]pp", "*.[ch]xx", "*.hh",  "*.inl",
        "*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in",
    ]),
    ("creole", &["*.creole"]),
    ("crystal", &["Projectfile", "*.cr", "*.ecr", "shard.yml"]),
    ("cs", &["*.cs"]),
    ("csharp", &["*.cs"]),
    ("cshtml", &["*.cshtml"]),
    ("css", &["*.css", "*.scss"]),
    ("csv", &["*.csv"]),
    ("cuda", &["*.cu", "*.cuh"]),
    ("cython", &["*.pyx", "*.pxi", "*.pxd"]),
    ("d", &["*.d"]),
    ("dart", &["*.dart"]),
    ("devicetree", &["*.dts", "*.dtsi"]),
    ("dhall", &["*.dhall"]),
    ("diff", &["*.patch", "*.diff"]),
    ("docker", &["*Dockerfile*"]),
    ("dts", &["*.dts", "*.dtsi"]),
    ("dvc", &["Dvcfile", "*.dvc"]),
    ("ebuild", &["*.ebuild"]),
    ("edn", &["*.edn"]),
    ("elisp", &["*.el"]),
    ("elixir", &["*.ex", "*.eex", "*.exs"]),
    ("elm", &["*.elm"]),
    ("erb", &["*.erb"]),
    ("erlang", &["*.erl", "*.hrl"]),
    ("fennel", &["*.fnl"]),
    ("fidl", &["*.fidl"]),
    ("fish", &["*.fish"]),
    ("flatbuffers", &["*.fbs"]),
    ("fortran", &[
        "*.f", "*.F", "*.f77", "*.F77", "*.pfo",
        "*.f90", "*.F90", "*.f95", "*.F95",
    ]),
    ("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
    ("fut", &["*.fut"]),
    ("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
    ("gn", &["*.gn", "*.gni"]),
    ("go", &["*.go"]),
    ("gradle", &["*.gradle"]),
    ("groovy", &["*.groovy", "*.gradle"]),
    ("gzip", &["*.gz", "*.tgz"]),
    ("h", &["*.h", "*.hh", "*.hpp"]),
    ("haml", &["*.haml"]),
    ("hare", &["*.ha"]),
    ("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]),
    ("hbs", &["*.hbs"]),
    ("hs", &["*.hs", "*.lhs"]),
    ("html", &["*.htm", "*.html", "*.ejs"]),
    ("hy", &["*.hy"]),
    ("idris", &["*.idr", "*.lidr"]),
    ("janet", &["*.janet"]),
    ("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]),
    ("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
    ("jl", &["*.jl"]),
    ("js", &["*.js", "*.jsx", "*.vue", "*.cjs", "*.mjs"]),
    ("json", &["*.json", "composer.lock"]),
    ("jsonl", &["*.jsonl"]),
    ("julia", &["*.jl"]),
    ("jupyter", &["*.ipynb", "*.jpynb"]),
    ("k", &["*.k"]),
    ("kotlin", &["*.kt", "*.kts"]),
    ("less", &["*.less"]),
    ("license", &[
        // General
        "COPYING", "COPYING[.-]*",
        "COPYRIGHT", "COPYRIGHT[.-]*",
        "EULA", "EULA[.-]*",
        "licen[cs]e", "licen[cs]e.*",
        "LICEN[CS]E", "LICEN[CS]E[.-]*", "*[.-]LICEN[CS]E*",
        "NOTICE", "NOTICE[.-]*",
        "PATENTS", "PATENTS[.-]*",
        "UNLICEN[CS]E", "UNLICEN[CS]E[.-]*",
        // GPL (gpl.txt, etc.)
        "agpl[.-]*",
        "gpl[.-]*",
        "lgpl[.-]*",
        // Other license-specific (APACHE-2.0.txt, etc.)
        "AGPL-*[0-9]*",
        "APACHE-*[0-9]*",
        "BSD-*[0-9]*",
        "CC-BY-*",
        "GFDL-*[0-9]*",
        "GNU-*[0-9]*",
        "GPL-*[0-9]*",
        "LGPL-*[0-9]*",
        "MIT-*[0-9]*",
        "MPL-*[0-9]*",
        "OFL-*[0-9]*",
    ]),
    ("lilypond", &["*.ly", "*.ily"]),
    ("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
    ("lock", &["*.lock", "package-lock.json"]),
    ("log", &["*.log"]),
    ("lua", &["*.lua"]),
    ("lz4", &["*.lz4"]),
    ("lzma", &["*.lzma"]),
    ("m4", &["*.ac", "*.m4"]),
    ("make", &[
        "[Gg][Nn][Uu]makefile", "[Mm]akefile",
        "[Gg][Nn][Uu]makefile.am", "[Mm]akefile.am",
        "[Gg][Nn][Uu]makefile.in", "[Mm]akefile.in",
        "*.mk", "*.mak"
    ]),
    ("mako", &["*.mako", "*.mao"]),
    ("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]),
    ("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]),
    ("matlab", &["*.m"]),
    ("md", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]),
    ("meson", &["meson.build", "meson_options.txt"]),
    ("minified", &["*.min.html", "*.min.css", "*.min.js"]),
    ("mint", &["*.mint"]),
    ("mk", &["mkfile"]),
    ("ml", &["*.ml"]),
    ("motoko", &["*.mo"]),
    ("msbuild", &[
        "*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets",
    ]),
    ("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]),
    ("nix", &["*.nix"]),
    ("objc", &["*.h", "*.m"]),
    ("objcpp", &["*.h", "*.mm"]),
    ("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
    ("org", &["*.org", "*.org_archive"]),
    ("pants", &["BUILD"]),
    ("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]),
    ("pdf", &["*.pdf"]),
    ("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]),
    ("php", &[
        // note that PHP 6 doesn't exist
        // See: https://wiki.php.net/rfc/php6
        "*.php", "*.php3", "*.php4", "*.php5", "*.php7", "*.php8",
        "*.pht", "*.phtml"
    ]),
    ("po", &["*.po"]),
    ("pod", &["*.pod"]),
    ("postscript", &["*.eps", "*.ps"]),
    ("protobuf", &["*.proto"]),
    ("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
    ("puppet", &["*.epp", "*.erb", "*.pp", "*.rb"]),
    ("purs", &["*.purs"]),
    ("py", &["*.py"]),
    ("qmake", &["*.pro", "*.pri", "*.prf"]),
    ("qml", &["*.qml"]),
    ("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
    ("racket", &["*.rkt"]),
    ("rdoc", &["*.rdoc"]),
    ("readme", &["README*", "*README"]),
    ("reasonml", &["*.re", "*.rei"]),
    ("red", &["*.r", "*.red", "*.reds"]),
    ("rescript", &["*.res", "*.resi"]),
    ("robot", &["*.robot"]),
    ("rst", &["*.rst"]),
    ("ruby", &[
        // Idiomatic files
        "config.ru", "Gemfile", ".irbrc", "Rakefile",
        // Extensions
        "*.gemspec", "*.rb", "*.rbw"
    ]),
    ("rust", &["*.rs"]),
    ("sass", &["*.sass", "*.scss"]),
    ("scala", &["*.scala", "*.sbt"]),
    ("sh", &[
        // Portable/misc. init files
        ".login", ".logout", ".profile", "profile",
        // bash-specific init files
        ".bash_login", "bash_login",
        ".bash_logout", "bash_logout",
        ".bash_profile", "bash_profile",
        ".bashrc", "bashrc", "*.bashrc",
        // csh-specific init files
        ".cshrc", "*.cshrc",
        // ksh-specific init files
        ".kshrc", "*.kshrc",
        // tcsh-specific init files
        ".tcshrc",
        // zsh-specific init files
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        // Extensions
        "*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh", "*.zsh",
    ]),
    ("slim", &["*.skim", "*.slim", "*.slime"]),
    ("smarty", &["*.tpl"]),
    ("sml", &["*.sml", "*.sig"]),
    ("solidity", &["*.sol"]),
    ("soy", &["*.soy"]),
    ("spark", &["*.spark"]),
    ("spec", &["*.spec"]),
    ("sql", &["*.sql", "*.psql"]),
    ("stylus", &["*.styl"]),
    ("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
    ("svg", &["*.svg"]),
    ("swift", &["*.swift"]),
    ("swig", &["*.def", "*.i"]),
    ("systemd", &[
        "*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path",
        "*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target",
        "*.timer",
    ]),
    ("taskpaper", &["*.taskpaper"]),
    ("tcl", &["*.tcl"]),
    ("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]),
    ("texinfo", &["*.texi"]),
    ("textile", &["*.textile"]),
    ("tf", &["*.tf"]),
    ("thrift", &["*.thrift"]),
    ("toml", &["*.toml", "Cargo.lock"]),
    ("ts", &["*.ts", "*.tsx", "*.cts", "*.mts"]),
    ("twig", &["*.twig"]),
    ("txt", &["*.txt"]),
    ("typoscript", &["*.typoscript", "*.ts"]),
    ("vala", &["*.vala"]),
    ("vb", &["*.vb"]),
    ("vcl", &["*.vcl"]),
    ("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]),
    ("vhdl", &["*.vhd", "*.vhdl"]),
    ("vim", &[
        "*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
    ]),
    ("vimscript", &[
        "*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
    ]),
    ("webidl", &["*.idl", "*.webidl", "*.widl"]),
    ("wiki", &["*.mediawiki", "*.wiki"]),
    ("xml", &[
        "*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb",
        "*.rng", "*.sch", "*.xhtml",
    ]),
    ("xz", &["*.xz", "*.txz"]),
    ("yacc", &["*.y"]),
    ("yaml", &["*.yaml", "*.yml"]),
    ("yang", &["*.yang"]),
    ("z", &["*.Z"]),
    ("zig", &["*.zig"]),
    ("zsh", &[
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        "*.zsh",
    ]),
    ("zstd", &["*.zst", "*.zstd"]),
];
<commit_msg>ignore/types: add automated test for sortedness<commit_after>/// This list represents the default file types that ripgrep ships with. In
/// general, any file format is fair game, although it should generally be
/// limited to reasonably popular open formats. For other cases, you can add
/// types to each invocation of ripgrep with the '--type-add' flag.
///
/// If you would like to add or improve this list, please file a PR:
/// <https://github.com/BurntSushi/ripgrep>.
///
/// Please try to keep this list sorted lexicographically and wrapped to 79
/// columns (inclusive).
#[rustfmt::skip]
pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
    ("agda", &["*.agda", "*.lagda"]),
    ("aidl", &["*.aidl"]),
    ("amake", &["*.mk", "*.bp"]),
    ("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
    ("asm", &["*.asm", "*.s", "*.S"]),
    ("asp", &[
        "*.aspx", "*.aspx.cs", "*.aspx.vb", "*.ascx", "*.ascx.cs",
        "*.ascx.vb", "*.asp"
    ]),
    ("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]),
    ("avro", &["*.avdl", "*.avpr", "*.avsc"]),
    ("awk", &["*.awk"]),
    ("bazel", &[
        "*.bazel", "*.bzl", "*.BUILD", "*.bazelrc", "BUILD", "MODULE.bazel",
        "WORKSPACE", "WORKSPACE.bazel",
    ]),
    ("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
    ("brotli", &["*.br"]),
    ("buildstream", &["*.bst"]),
    ("bzip2", &["*.bz2", "*.tbz2"]),
    ("c", &["*.[chH]", "*.[chH].in", "*.cats"]),
    ("cabal", &["*.cabal"]),
    ("candid", &["*.did"]),
    ("carp", &["*.carp"]),
    ("cbor", &["*.cbor"]),
    ("ceylon", &["*.ceylon"]),
    ("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
    ("cmake", &["*.cmake", "CMakeLists.txt"]),
    ("coffeescript", &["*.coffee"]),
    ("config", &["*.cfg", "*.conf", "*.config", "*.ini"]),
    ("coq", &["*.v"]),
    ("cpp", &[
        "*.[ChH]", "*.cc", "*.[ch]pp", "*.[ch]xx", "*.hh",  "*.inl",
        "*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in",
    ]),
    ("creole", &["*.creole"]),
    ("crystal", &["Projectfile", "*.cr", "*.ecr", "shard.yml"]),
    ("cs", &["*.cs"]),
    ("csharp", &["*.cs"]),
    ("cshtml", &["*.cshtml"]),
    ("css", &["*.css", "*.scss"]),
    ("csv", &["*.csv"]),
    ("cuda", &["*.cu", "*.cuh"]),
    ("cython", &["*.pyx", "*.pxi", "*.pxd"]),
    ("d", &["*.d"]),
    ("dart", &["*.dart"]),
    ("devicetree", &["*.dts", "*.dtsi"]),
    ("dhall", &["*.dhall"]),
    ("diff", &["*.patch", "*.diff"]),
    ("docker", &["*Dockerfile*"]),
    ("dts", &["*.dts", "*.dtsi"]),
    ("dvc", &["Dvcfile", "*.dvc"]),
    ("ebuild", &["*.ebuild"]),
    ("edn", &["*.edn"]),
    ("elisp", &["*.el"]),
    ("elixir", &["*.ex", "*.eex", "*.exs"]),
    ("elm", &["*.elm"]),
    ("erb", &["*.erb"]),
    ("erlang", &["*.erl", "*.hrl"]),
    ("fennel", &["*.fnl"]),
    ("fidl", &["*.fidl"]),
    ("fish", &["*.fish"]),
    ("flatbuffers", &["*.fbs"]),
    ("fortran", &[
        "*.f", "*.F", "*.f77", "*.F77", "*.pfo",
        "*.f90", "*.F90", "*.f95", "*.F95",
    ]),
    ("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
    ("fut", &["*.fut"]),
    ("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
    ("gn", &["*.gn", "*.gni"]),
    ("go", &["*.go"]),
    ("gradle", &["*.gradle"]),
    ("groovy", &["*.groovy", "*.gradle"]),
    ("gzip", &["*.gz", "*.tgz"]),
    ("h", &["*.h", "*.hh", "*.hpp"]),
    ("haml", &["*.haml"]),
    ("hare", &["*.ha"]),
    ("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]),
    ("hbs", &["*.hbs"]),
    ("hs", &["*.hs", "*.lhs"]),
    ("html", &["*.htm", "*.html", "*.ejs"]),
    ("hy", &["*.hy"]),
    ("idris", &["*.idr", "*.lidr"]),
    ("janet", &["*.janet"]),
    ("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]),
    ("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
    ("jl", &["*.jl"]),
    ("js", &["*.js", "*.jsx", "*.vue", "*.cjs", "*.mjs"]),
    ("json", &["*.json", "composer.lock"]),
    ("jsonl", &["*.jsonl"]),
    ("julia", &["*.jl"]),
    ("jupyter", &["*.ipynb", "*.jpynb"]),
    ("k", &["*.k"]),
    ("kotlin", &["*.kt", "*.kts"]),
    ("less", &["*.less"]),
    ("license", &[
        // General
        "COPYING", "COPYING[.-]*",
        "COPYRIGHT", "COPYRIGHT[.-]*",
        "EULA", "EULA[.-]*",
        "licen[cs]e", "licen[cs]e.*",
        "LICEN[CS]E", "LICEN[CS]E[.-]*", "*[.-]LICEN[CS]E*",
        "NOTICE", "NOTICE[.-]*",
        "PATENTS", "PATENTS[.-]*",
        "UNLICEN[CS]E", "UNLICEN[CS]E[.-]*",
        // GPL (gpl.txt, etc.)
        "agpl[.-]*",
        "gpl[.-]*",
        "lgpl[.-]*",
        // Other license-specific (APACHE-2.0.txt, etc.)
        "AGPL-*[0-9]*",
        "APACHE-*[0-9]*",
        "BSD-*[0-9]*",
        "CC-BY-*",
        "GFDL-*[0-9]*",
        "GNU-*[0-9]*",
        "GPL-*[0-9]*",
        "LGPL-*[0-9]*",
        "MIT-*[0-9]*",
        "MPL-*[0-9]*",
        "OFL-*[0-9]*",
    ]),
    ("lilypond", &["*.ly", "*.ily"]),
    ("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
    ("lock", &["*.lock", "package-lock.json"]),
    ("log", &["*.log"]),
    ("lua", &["*.lua"]),
    ("lz4", &["*.lz4"]),
    ("lzma", &["*.lzma"]),
    ("m4", &["*.ac", "*.m4"]),
    ("make", &[
        "[Gg][Nn][Uu]makefile", "[Mm]akefile",
        "[Gg][Nn][Uu]makefile.am", "[Mm]akefile.am",
        "[Gg][Nn][Uu]makefile.in", "[Mm]akefile.in",
        "*.mk", "*.mak"
    ]),
    ("mako", &["*.mako", "*.mao"]),
    ("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]),
    ("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]),
    ("matlab", &["*.m"]),
    ("md", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]),
    ("meson", &["meson.build", "meson_options.txt"]),
    ("minified", &["*.min.html", "*.min.css", "*.min.js"]),
    ("mint", &["*.mint"]),
    ("mk", &["mkfile"]),
    ("ml", &["*.ml"]),
    ("motoko", &["*.mo"]),
    ("msbuild", &[
        "*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets",
    ]),
    ("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]),
    ("nix", &["*.nix"]),
    ("objc", &["*.h", "*.m"]),
    ("objcpp", &["*.h", "*.mm"]),
    ("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
    ("org", &["*.org", "*.org_archive"]),
    ("pants", &["BUILD"]),
    ("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]),
    ("pdf", &["*.pdf"]),
    ("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]),
    ("php", &[
        // note that PHP 6 doesn't exist
        // See: https://wiki.php.net/rfc/php6
        "*.php", "*.php3", "*.php4", "*.php5", "*.php7", "*.php8",
        "*.pht", "*.phtml"
    ]),
    ("po", &["*.po"]),
    ("pod", &["*.pod"]),
    ("postscript", &["*.eps", "*.ps"]),
    ("protobuf", &["*.proto"]),
    ("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
    ("puppet", &["*.epp", "*.erb", "*.pp", "*.rb"]),
    ("purs", &["*.purs"]),
    ("py", &["*.py"]),
    ("qmake", &["*.pro", "*.pri", "*.prf"]),
    ("qml", &["*.qml"]),
    ("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
    ("racket", &["*.rkt"]),
    ("rdoc", &["*.rdoc"]),
    ("readme", &["README*", "*README"]),
    ("reasonml", &["*.re", "*.rei"]),
    ("red", &["*.r", "*.red", "*.reds"]),
    ("rescript", &["*.res", "*.resi"]),
    ("robot", &["*.robot"]),
    ("rst", &["*.rst"]),
    ("ruby", &[
        // Idiomatic files
        "config.ru", "Gemfile", ".irbrc", "Rakefile",
        // Extensions
        "*.gemspec", "*.rb", "*.rbw"
    ]),
    ("rust", &["*.rs"]),
    ("sass", &["*.sass", "*.scss"]),
    ("scala", &["*.scala", "*.sbt"]),
    ("sh", &[
        // Portable/misc. init files
        ".login", ".logout", ".profile", "profile",
        // bash-specific init files
        ".bash_login", "bash_login",
        ".bash_logout", "bash_logout",
        ".bash_profile", "bash_profile",
        ".bashrc", "bashrc", "*.bashrc",
        // csh-specific init files
        ".cshrc", "*.cshrc",
        // ksh-specific init files
        ".kshrc", "*.kshrc",
        // tcsh-specific init files
        ".tcshrc",
        // zsh-specific init files
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        // Extensions
        "*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh", "*.zsh",
    ]),
    ("slim", &["*.skim", "*.slim", "*.slime"]),
    ("smarty", &["*.tpl"]),
    ("sml", &["*.sml", "*.sig"]),
    ("solidity", &["*.sol"]),
    ("soy", &["*.soy"]),
    ("spark", &["*.spark"]),
    ("spec", &["*.spec"]),
    ("sql", &["*.sql", "*.psql"]),
    ("stylus", &["*.styl"]),
    ("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
    ("svg", &["*.svg"]),
    ("swift", &["*.swift"]),
    ("swig", &["*.def", "*.i"]),
    ("systemd", &[
        "*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path",
        "*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target",
        "*.timer",
    ]),
    ("taskpaper", &["*.taskpaper"]),
    ("tcl", &["*.tcl"]),
    ("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]),
    ("texinfo", &["*.texi"]),
    ("textile", &["*.textile"]),
    ("tf", &["*.tf"]),
    ("thrift", &["*.thrift"]),
    ("toml", &["*.toml", "Cargo.lock"]),
    ("ts", &["*.ts", "*.tsx", "*.cts", "*.mts"]),
    ("twig", &["*.twig"]),
    ("txt", &["*.txt"]),
    ("typoscript", &["*.typoscript", "*.ts"]),
    ("vala", &["*.vala"]),
    ("vb", &["*.vb"]),
    ("vcl", &["*.vcl"]),
    ("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]),
    ("vhdl", &["*.vhd", "*.vhdl"]),
    ("vim", &[
        "*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
    ]),
    ("vimscript", &[
        "*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
    ]),
    ("webidl", &["*.idl", "*.webidl", "*.widl"]),
    ("wiki", &["*.mediawiki", "*.wiki"]),
    ("xml", &[
        "*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb",
        "*.rng", "*.sch", "*.xhtml",
    ]),
    ("xz", &["*.xz", "*.txz"]),
    ("yacc", &["*.y"]),
    ("yaml", &["*.yaml", "*.yml"]),
    ("yang", &["*.yang"]),
    ("z", &["*.Z"]),
    ("zig", &["*.zig"]),
    ("zsh", &[
        ".zshenv", "zshenv",
        ".zlogin", "zlogin",
        ".zlogout", "zlogout",
        ".zprofile", "zprofile",
        ".zshrc", "zshrc",
        "*.zsh",
    ]),
    ("zstd", &["*.zst", "*.zstd"]),
];

#[cfg(test)]
mod tests {
    use super::DEFAULT_TYPES;

    #[test]
    fn default_types_are_sorted() {
        let mut names = DEFAULT_TYPES.iter().map(|(name, _exts)| name);

        let Some(mut previous_name) = names.next() else { return; };

        for name in names {
            assert!(
                name > previous_name,
                r#""{}" should be sorted before "{}" in `DEFAULT_TYPES`"#,
                name,
                previous_name
            );

            previous_name = name;
        }
    }
}
<|endoftext|>


<commit_before>//! A simple adaptive threadpool that returns a oneshot future.
use super::OneShot;

/// Spawn a function on the threadpool.
pub fn spawn<F, R>(work: F) -> OneShot<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    let (promise_filler, promise) = OneShot::pair();
    let task = move || {
        let result = (work)();
        promise_filler.fill(result);
    };

    // On windows, linux, and macos send it to a threadpool.
    // Otherwise just execute it immediately, because we may
    // not support threads at all!
    #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
    {
        (task)();
        return promise;
    }

    #[cfg(any(windows, target_os = "linux", target_os = "macos"))]
    {
        use std::sync::atomic::{AtomicU64, Ordering};
        use std::thread;
        use std::time::Duration;

        use crossbeam_channel::{bounded, Receiver, Sender};

        use super::{debug_delay, Lazy};

        const MAX_THREADS: u64 = 10_000;

        static DYNAMIC_THREAD_COUNT: AtomicU64 = AtomicU64::new(0);

        struct Pool {
            sender: Sender<Box<dyn FnOnce() + Send + 'static>>,
            receiver: Receiver<Box<dyn FnOnce() + Send + 'static>>,
        }

        static POOL: Lazy<Pool, fn() -> Pool> = Lazy::new(init_pool);

        fn init_pool() -> Pool {
            for _ in 0..2 {
                thread::Builder::new()
                    .name("sled-io".to_string())
                    .spawn(|| {
                        for task in &POOL.receiver {
                            debug_delay();
                            (task)()
                        }
                    })
                    .expect("cannot start a thread driving blocking tasks");
            }

            // We want to use an unbuffered channel here to help
            // us drive our dynamic control. In effect, the
            // kernel's scheduler becomes the queue, reducing
            // the number of buffers that work must flow through
            // before being acted on by a core. This helps keep
            // latency snappy in the overall async system by
            // reducing bufferbloat.
            let (sender, receiver) = bounded(0);
            Pool { sender, receiver }
        }

        // Create up to MAX_THREADS dynamic blocking task worker threads.
        // Dynamic threads will terminate themselves if they don't
        // receive any work after one second.
        fn maybe_create_another_blocking_thread() {
            // We use a `Relaxed` atomic operation because
            // it's just a heuristic, and would not lose correctness
            // even if it's random.
            let workers = DYNAMIC_THREAD_COUNT.load(Ordering::Relaxed);
            if workers >= MAX_THREADS {
                return;
            }

            thread::Builder::new()
                .name("sled-io".to_string())
                .spawn(|| {
                    let wait_limit = Duration::from_secs(1);

                    DYNAMIC_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
                    while let Ok(task) = POOL.receiver.recv_timeout(wait_limit)
                    {
                        debug_delay();
                        (task)();
                    }
                    DYNAMIC_THREAD_COUNT.fetch_sub(1, Ordering::Relaxed);
                })
                .expect("cannot start a dynamic thread driving blocking tasks");
        }

        let first_try_result = POOL.sender.try_send(Box::new(task));
        match first_try_result {
            Ok(()) => {
                // NICEEEE
            }
            Err(crossbeam_channel::TrySendError::Full(task)) => {
                // We were not able to send to the channel without
                // blocking. Try to spin up another thread and then
                // retry sending while blocking.
                maybe_create_another_blocking_thread();
                POOL.sender.send(task).unwrap()
            }
            Err(crossbeam_channel::TrySendError::Disconnected(_)) => {
                panic!(
                    "unable to send to blocking threadpool \
                     due to receiver disconnection"
                );
            }
        }

        promise
    }
}
<commit_msg>Tune the number of blocking threads way down.<commit_after>//! A simple adaptive threadpool that returns a oneshot future.

use log::warn;

use super::OneShot;

/// Spawn a function on the threadpool.
pub fn spawn<F, R>(work: F) -> OneShot<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    let (promise_filler, promise) = OneShot::pair();
    let task = move || {
        let result = (work)();
        promise_filler.fill(result);
    };

    // On windows, linux, and macos send it to a threadpool.
    // Otherwise just execute it immediately, because we may
    // not support threads at all!
    #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
    {
        (task)();
        return promise;
    }

    #[cfg(any(windows, target_os = "linux", target_os = "macos"))]
    {
        use std::sync::atomic::{AtomicU64, Ordering};
        use std::thread;
        use std::time::Duration;

        use crossbeam_channel::{bounded, Receiver, Sender};

        use super::{debug_delay, Lazy};

        const MAX_THREADS: u64 = 128;

        static DYNAMIC_THREAD_COUNT: AtomicU64 = AtomicU64::new(0);

        struct Pool {
            sender: Sender<Box<dyn FnOnce() + Send + 'static>>,
            receiver: Receiver<Box<dyn FnOnce() + Send + 'static>>,
        }

        static POOL: Lazy<Pool, fn() -> Pool> = Lazy::new(init_pool);

        fn init_pool() -> Pool {
            for _ in 0..2 {
                thread::Builder::new()
                    .name("sled-io".to_string())
                    .spawn(|| {
                        for task in &POOL.receiver {
                            debug_delay();
                            (task)()
                        }
                    })
                    .expect("cannot start a thread driving blocking tasks");
            }

            // We want to use an unbuffered channel here to help
            // us drive our dynamic control. In effect, the
            // kernel's scheduler becomes the queue, reducing
            // the number of buffers that work must flow through
            // before being acted on by a core. This helps keep
            // latency snappy in the overall async system by
            // reducing bufferbloat.
            let (sender, receiver) = bounded(0);
            Pool { sender, receiver }
        }

        // Create up to MAX_THREADS dynamic blocking task worker threads.
        // Dynamic threads will terminate themselves if they don't
        // receive any work after one second.
        fn maybe_create_another_blocking_thread() {
            // We use a `Relaxed` atomic operation because
            // it's just a heuristic, and would not lose correctness
            // even if it's random.
            let workers = DYNAMIC_THREAD_COUNT.load(Ordering::Relaxed);
            if workers >= MAX_THREADS {
                return;
            }

            let spawn_res = thread::Builder::new()
                .name("sled-io".to_string())
                .spawn(|| {
                    let wait_limit = Duration::from_secs(1);

                    DYNAMIC_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
                    while let Ok(task) = POOL.receiver.recv_timeout(wait_limit)
                    {
                        debug_delay();
                        (task)();
                    }
                    DYNAMIC_THREAD_COUNT.fetch_sub(1, Ordering::Relaxed);
                });

            if let Err(e) = spawn_res {
                warn!(
                    "Failed to dynamically increase the threadpool size: {:?}. \
                     Currently have {} dynamic threads",
                    e,
                    workers
                );
            }
        }

        let first_try_result = POOL.sender.try_send(Box::new(task));
        match first_try_result {
            Ok(()) => {
                // NICEEEE
            }
            Err(crossbeam_channel::TrySendError::Full(task)) => {
                // We were not able to send to the channel without
                // blocking. Try to spin up another thread and then
                // retry sending while blocking.
                maybe_create_another_blocking_thread();
                POOL.sender.send(task).unwrap()
            }
            Err(crossbeam_channel::TrySendError::Disconnected(_)) => {
                panic!(
                    "unable to send to blocking threadpool \
                     due to receiver disconnection"
                );
            }
        }

        promise
    }
}
<|endoftext|>


<commit_before>//! Project loading & configuration updates
use std::sync::Arc;

use crossbeam_channel::unbounded;
use flycheck::FlycheckHandle;
use ra_db::{CrateGraph, SourceRoot, VfsPath};
use ra_ide::AnalysisChange;
use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace};
use vfs::{file_set::FileSetConfig, AbsPath};

use crate::{
    config::{Config, FilesWatcher, LinkedProject},
    global_state::{GlobalState, Handle},
};

impl GlobalState {
    pub(crate) fn update_configuration(&mut self, new_config: Config) {
        self.analysis_host.update_lru_capacity(new_config.lru_capacity);
        if new_config.flycheck != self.config.flycheck {
            self.reload_flycheck();
        }
        self.config = new_config;
    }
    pub(crate) fn reload(&mut self) {
        let workspaces = {
            if self.config.linked_projects.is_empty()
                && self.config.notifications.cargo_toml_not_found
            {
                self.show_message(
                    lsp_types::MessageType::Error,
                    "rust-analyzer failed to discover workspace".to_string(),
                );
            };

            self.config
                .linked_projects
                .iter()
                .map(|project| match project {
                    LinkedProject::ProjectManifest(manifest) => {
                        ra_project_model::ProjectWorkspace::load(
                            manifest.clone(),
                            &self.config.cargo,
                            self.config.with_sysroot,
                        )
                    }
                    LinkedProject::InlineJsonProject(it) => {
                        Ok(ra_project_model::ProjectWorkspace::Json { project: it.clone() })
                    }
                })
                .collect::<Vec<_>>()
                .into_iter()
                .filter_map(|res| {
                    res.map_err(|err| {
                        log::error!("failed to load workspace: {:#}", err);
                        self.show_message(
                            lsp_types::MessageType::Error,
                            format!("rust-analyzer failed to load workspace: {:#}", err),
                        );
                    })
                    .ok()
                })
                .collect::<Vec<_>>()
        };

        if let FilesWatcher::Client = self.config.files.watcher {
            let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
                watchers: workspaces
                    .iter()
                    .flat_map(ProjectWorkspace::to_roots)
                    .filter(PackageRoot::is_member)
                    .map(|root| format!("{}/**/*.rs", root.path().display()))
                    .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
                    .collect(),
            };
            let registration = lsp_types::Registration {
                id: "file-watcher".to_string(),
                method: "workspace/didChangeWatchedFiles".to_string(),
                register_options: Some(serde_json::to_value(registration_options).unwrap()),
            };
            self.send_request::<lsp_types::request::RegisterCapability>(
                lsp_types::RegistrationParams { registrations: vec![registration] },
                |_, _| (),
            );
        }

        let mut change = AnalysisChange::new();

        let project_folders = ProjectFolders::new(&workspaces);

        self.proc_macro_client = match &self.config.proc_macro_srv {
            None => ProcMacroClient::dummy(),
            Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
                Ok(it) => it,
                Err(err) => {
                    log::error!(
                        "Failed to run ra_proc_macro_srv from path {}, error: {:?}",
                        path.display(),
                        err
                    );
                    ProcMacroClient::dummy()
                }
            },
        };
        let watch = match self.config.files.watcher {
            FilesWatcher::Client => vec![],
            FilesWatcher::Notify => project_folders.watch,
        };
        self.loader.handle.set_config(vfs::loader::Config { load: project_folders.load, watch });

        // Create crate graph from all the workspaces
        let crate_graph = {
            let mut crate_graph = CrateGraph::default();
            let vfs = &mut self.vfs.write().0;
            let loader = &mut self.loader;
            let mut load = |path: &AbsPath| {
                let contents = loader.handle.load_sync(path);
                let path = vfs::VfsPath::from(path.to_path_buf());
                vfs.set_file_contents(path.clone(), contents);
                vfs.file_id(&path)
            };
            for ws in workspaces.iter() {
                crate_graph.extend(ws.to_crate_graph(
                    self.config.cargo.target.as_deref(),
                    &self.proc_macro_client,
                    &mut load,
                ));
            }

            crate_graph
        };
        change.set_crate_graph(crate_graph);

        self.source_root_config = project_folders.source_root_config;
        self.workspaces = Arc::new(workspaces);

        self.analysis_host.apply_change(change);
        self.process_changes();
        self.reload_flycheck();
    }

    fn reload_flycheck(&mut self) {
        let config = match self.config.flycheck.clone() {
            Some(it) => it,
            None => {
                self.flycheck = None;
                return;
            }
        };

        // FIXME: Figure out the multi-workspace situation
        self.flycheck = self.workspaces.iter().find_map(move |w| match w {
            ProjectWorkspace::Cargo { cargo, .. } => {
                let (sender, receiver) = unbounded();
                let sender = Box::new(move |msg| sender.send(msg).unwrap());
                let cargo_project_root = cargo.workspace_root().to_path_buf();
                let handle =
                    FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into());
                Some(Handle { handle, receiver })
            }
            ProjectWorkspace::Json { .. } => {
                log::warn!("Cargo check watching only supported for cargo workspaces, disabling");
                None
            }
        })
    }
}

#[derive(Default)]
pub(crate) struct ProjectFolders {
    pub(crate) load: Vec<vfs::loader::Entry>,
    pub(crate) watch: Vec<usize>,
    pub(crate) source_root_config: SourceRootConfig,
}

impl ProjectFolders {
    pub(crate) fn new(workspaces: &[ProjectWorkspace]) -> ProjectFolders {
        let mut res = ProjectFolders::default();
        let mut fsc = FileSetConfig::builder();
        let mut local_filesets = vec![];

        for root in workspaces.iter().flat_map(|it| it.to_roots()) {
            let path = root.path().to_owned();

            let mut file_set_roots: Vec<VfsPath> = vec![];

            let entry = if root.is_member() {
                vfs::loader::Entry::local_cargo_package(path.to_path_buf())
            } else {
                vfs::loader::Entry::cargo_package_dependency(path.to_path_buf())
            };
            res.load.push(entry);
            if root.is_member() {
                res.watch.push(res.load.len() - 1);
            }

            if let Some(out_dir) = root.out_dir() {
                let out_dir = out_dir.to_path_buf();
                res.load.push(vfs::loader::Entry::rs_files_recursively(out_dir.clone()));
                if root.is_member() {
                    res.watch.push(res.load.len() - 1);
                }
                file_set_roots.push(out_dir.into());
            }
            file_set_roots.push(path.to_path_buf().into());

            if root.is_member() {
                local_filesets.push(fsc.len());
            }
            fsc.add_file_set(file_set_roots)
        }

        let fsc = fsc.build();
        res.source_root_config = SourceRootConfig { fsc, local_filesets };

        res
    }
}

#[derive(Default, Debug)]
pub(crate) struct SourceRootConfig {
    pub(crate) fsc: FileSetConfig,
    pub(crate) local_filesets: Vec<usize>,
}

impl SourceRootConfig {
    pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
        self.fsc
            .partition(vfs)
            .into_iter()
            .enumerate()
            .map(|(idx, file_set)| {
                let is_local = self.local_filesets.contains(&idx);
                if is_local {
                    SourceRoot::new_local(file_set)
                } else {
                    SourceRoot::new_library(file_set)
                }
            })
            .collect()
    }
}
<commit_msg>Fix config switching<commit_after>//! Project loading & configuration updates
use std::{mem, sync::Arc};

use crossbeam_channel::unbounded;
use flycheck::FlycheckHandle;
use ra_db::{CrateGraph, SourceRoot, VfsPath};
use ra_ide::AnalysisChange;
use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace};
use vfs::{file_set::FileSetConfig, AbsPath};

use crate::{
    config::{Config, FilesWatcher, LinkedProject},
    global_state::{GlobalState, Handle},
};

impl GlobalState {
    pub(crate) fn update_configuration(&mut self, config: Config) {
        let old_config = mem::replace(&mut self.config, config);
        if self.config.lru_capacity != old_config.lru_capacity {
            self.analysis_host.update_lru_capacity(old_config.lru_capacity);
        }
        if self.config.flycheck != old_config.flycheck {
            self.reload_flycheck();
        }
    }
    pub(crate) fn reload(&mut self) {
        let workspaces = {
            if self.config.linked_projects.is_empty()
                && self.config.notifications.cargo_toml_not_found
            {
                self.show_message(
                    lsp_types::MessageType::Error,
                    "rust-analyzer failed to discover workspace".to_string(),
                );
            };

            self.config
                .linked_projects
                .iter()
                .map(|project| match project {
                    LinkedProject::ProjectManifest(manifest) => {
                        ra_project_model::ProjectWorkspace::load(
                            manifest.clone(),
                            &self.config.cargo,
                            self.config.with_sysroot,
                        )
                    }
                    LinkedProject::InlineJsonProject(it) => {
                        Ok(ra_project_model::ProjectWorkspace::Json { project: it.clone() })
                    }
                })
                .collect::<Vec<_>>()
                .into_iter()
                .filter_map(|res| {
                    res.map_err(|err| {
                        log::error!("failed to load workspace: {:#}", err);
                        self.show_message(
                            lsp_types::MessageType::Error,
                            format!("rust-analyzer failed to load workspace: {:#}", err),
                        );
                    })
                    .ok()
                })
                .collect::<Vec<_>>()
        };

        if let FilesWatcher::Client = self.config.files.watcher {
            let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
                watchers: workspaces
                    .iter()
                    .flat_map(ProjectWorkspace::to_roots)
                    .filter(PackageRoot::is_member)
                    .map(|root| format!("{}/**/*.rs", root.path().display()))
                    .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
                    .collect(),
            };
            let registration = lsp_types::Registration {
                id: "file-watcher".to_string(),
                method: "workspace/didChangeWatchedFiles".to_string(),
                register_options: Some(serde_json::to_value(registration_options).unwrap()),
            };
            self.send_request::<lsp_types::request::RegisterCapability>(
                lsp_types::RegistrationParams { registrations: vec![registration] },
                |_, _| (),
            );
        }

        let mut change = AnalysisChange::new();

        let project_folders = ProjectFolders::new(&workspaces);

        self.proc_macro_client = match &self.config.proc_macro_srv {
            None => ProcMacroClient::dummy(),
            Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
                Ok(it) => it,
                Err(err) => {
                    log::error!(
                        "Failed to run ra_proc_macro_srv from path {}, error: {:?}",
                        path.display(),
                        err
                    );
                    ProcMacroClient::dummy()
                }
            },
        };
        let watch = match self.config.files.watcher {
            FilesWatcher::Client => vec![],
            FilesWatcher::Notify => project_folders.watch,
        };
        self.loader.handle.set_config(vfs::loader::Config { load: project_folders.load, watch });

        // Create crate graph from all the workspaces
        let crate_graph = {
            let mut crate_graph = CrateGraph::default();
            let vfs = &mut self.vfs.write().0;
            let loader = &mut self.loader;
            let mut load = |path: &AbsPath| {
                let contents = loader.handle.load_sync(path);
                let path = vfs::VfsPath::from(path.to_path_buf());
                vfs.set_file_contents(path.clone(), contents);
                vfs.file_id(&path)
            };
            for ws in workspaces.iter() {
                crate_graph.extend(ws.to_crate_graph(
                    self.config.cargo.target.as_deref(),
                    &self.proc_macro_client,
                    &mut load,
                ));
            }

            crate_graph
        };
        change.set_crate_graph(crate_graph);

        self.source_root_config = project_folders.source_root_config;
        self.workspaces = Arc::new(workspaces);

        self.analysis_host.apply_change(change);
        self.process_changes();
        self.reload_flycheck();
    }

    fn reload_flycheck(&mut self) {
        let config = match self.config.flycheck.clone() {
            Some(it) => it,
            None => {
                self.flycheck = None;
                return;
            }
        };

        // FIXME: Figure out the multi-workspace situation
        self.flycheck = self.workspaces.iter().find_map(move |w| match w {
            ProjectWorkspace::Cargo { cargo, .. } => {
                let (sender, receiver) = unbounded();
                let sender = Box::new(move |msg| sender.send(msg).unwrap());
                let cargo_project_root = cargo.workspace_root().to_path_buf();
                let handle =
                    FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into());
                Some(Handle { handle, receiver })
            }
            ProjectWorkspace::Json { .. } => {
                log::warn!("Cargo check watching only supported for cargo workspaces, disabling");
                None
            }
        })
    }
}

#[derive(Default)]
pub(crate) struct ProjectFolders {
    pub(crate) load: Vec<vfs::loader::Entry>,
    pub(crate) watch: Vec<usize>,
    pub(crate) source_root_config: SourceRootConfig,
}

impl ProjectFolders {
    pub(crate) fn new(workspaces: &[ProjectWorkspace]) -> ProjectFolders {
        let mut res = ProjectFolders::default();
        let mut fsc = FileSetConfig::builder();
        let mut local_filesets = vec![];

        for root in workspaces.iter().flat_map(|it| it.to_roots()) {
            let path = root.path().to_owned();

            let mut file_set_roots: Vec<VfsPath> = vec![];

            let entry = if root.is_member() {
                vfs::loader::Entry::local_cargo_package(path.to_path_buf())
            } else {
                vfs::loader::Entry::cargo_package_dependency(path.to_path_buf())
            };
            res.load.push(entry);
            if root.is_member() {
                res.watch.push(res.load.len() - 1);
            }

            if let Some(out_dir) = root.out_dir() {
                let out_dir = out_dir.to_path_buf();
                res.load.push(vfs::loader::Entry::rs_files_recursively(out_dir.clone()));
                if root.is_member() {
                    res.watch.push(res.load.len() - 1);
                }
                file_set_roots.push(out_dir.into());
            }
            file_set_roots.push(path.to_path_buf().into());

            if root.is_member() {
                local_filesets.push(fsc.len());
            }
            fsc.add_file_set(file_set_roots)
        }

        let fsc = fsc.build();
        res.source_root_config = SourceRootConfig { fsc, local_filesets };

        res
    }
}

#[derive(Default, Debug)]
pub(crate) struct SourceRootConfig {
    pub(crate) fsc: FileSetConfig,
    pub(crate) local_filesets: Vec<usize>,
}

impl SourceRootConfig {
    pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
        self.fsc
            .partition(vfs)
            .into_iter()
            .enumerate()
            .map(|(idx, file_set)| {
                let is_local = self.local_filesets.contains(&idx);
                if is_local {
                    SourceRoot::new_local(file_set)
                } else {
                    SourceRoot::new_library(file_set)
                }
            })
            .collect()
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

type MyResultPriv<T> = Result<T, u16>;
pub type MyResultPub<T> = Result<T, u64>;

// @has private_type_alias/fn.get_result_priv.html '//pre' 'Result<u8, u16>'
pub fn get_result_priv() -> MyResultPriv<u8> {
    panic!();
}

// @has private_type_alias/fn.get_result_pub.html '//pre' 'MyResultPub<u32>'
pub fn get_result_pub() -> MyResultPub<u32> {
    panic!();
}

type MyLifetimePriv<'a> = &'a isize;

// @has private_type_alias/fn.get_lifetime_priv.html '//pre' "&'static isize"
pub fn get_lifetime_priv() -> MyLifetimePriv<'static> {
    panic!();
}
<commit_msg>Add test for recursive private alias substitution in rustdoc<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

type MyResultPriv<T> = Result<T, u16>;
pub type MyResultPub<T> = Result<T, u64>;

// @has private_type_alias/fn.get_result_priv.html '//pre' 'Result<u8, u16>'
pub fn get_result_priv() -> MyResultPriv<u8> {
    panic!();
}

// @has private_type_alias/fn.get_result_pub.html '//pre' 'MyResultPub<u32>'
pub fn get_result_pub() -> MyResultPub<u32> {
    panic!();
}

pub type PubRecursive = u16;
type PrivRecursive3 = u8;
type PrivRecursive2 = PubRecursive;
type PrivRecursive1 = PrivRecursive3;

// PrivRecursive1 is expanded twice and stops at u8
// PrivRecursive2 is expanded once and stops at public type alias PubRecursive
// @has private_type_alias/fn.get_result_recursive.html '//pre' '(u8, PubRecursive)'
pub fn get_result_recursive() -> (PrivRecursive1, PrivRecursive2) {
    panic!();
}

type MyLifetimePriv<'a> = &'a isize;

// @has private_type_alias/fn.get_lifetime_priv.html '//pre' "&'static isize"
pub fn get_lifetime_priv() -> MyLifetimePriv<'static> {
    panic!();
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Maciej Dziardziel <fiedzia@gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.

// spell-checker:ignore (vars/api) fcntl setrlimit setitimer
// spell-checker:ignore (vars/signals) ABRT ALRM CHLD SEGV SIGABRT SIGALRM SIGBUS SIGCHLD SIGCONT SIGEMT SIGFPE SIGHUP SIGILL SIGINFO SIGINT SIGIO SIGIOT SIGKILL SIGPIPE SIGPROF SIGQUIT SIGSEGV SIGSTOP SIGSYS SIGTERM SIGTRAP SIGTSTP SIGTTIN SIGTTOU SIGURG SIGUSR SIGVTALRM SIGWINCH SIGXCPU SIGXFSZ STKFLT TSTP TTIN TTOU VTALRM XCPU XFSZ

pub static DEFAULT_SIGNAL: usize = 15;

/*

Linux Programmer's Manual

 1 HUP      2 INT      3 QUIT     4 ILL      5 TRAP     6 ABRT     7 BUS
 8 FPE      9 KILL    10 USR1    11 SEGV    12 USR2    13 PIPE    14 ALRM
15 TERM    16 STKFLT  17 CHLD    18 CONT    19 STOP    20 TSTP    21 TTIN
22 TTOU    23 URG     24 XCPU    25 XFSZ    26 VTALRM  27 PROF    28 WINCH
29 POLL    30 PWR     31 SYS

*/

#[cfg(any(target_os = "linux", target_os = "android"))]
pub static ALL_SIGNALS: [&str; 32] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV",
    "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU",
    "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "POLL", "PWR", "SYS",
];

/*

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html

No    Name         Default Action       Description
1     SIGHUP       terminate process    terminal line hangup
2     SIGINT       terminate process    interrupt program
3     SIGQUIT      create core image    quit program
4     SIGILL       create core image    illegal instruction
5     SIGTRAP      create core image    trace trap
6     SIGABRT      create core image    abort program (formerly SIGIOT)
7     SIGEMT       create core image    emulate instruction executed
8     SIGFPE       create core image    floating-point exception
9     SIGKILL      terminate process    kill program
10    SIGBUS       create core image    bus error
11    SIGSEGV      create core image    segmentation violation
12    SIGSYS       create core image    non-existent system call invoked
13    SIGPIPE      terminate process    write on a pipe with no reader
14    SIGALRM      terminate process    real-time timer expired
15    SIGTERM      terminate process    software termination signal
16    SIGURG       discard signal       urgent condition present on socket
17    SIGSTOP      stop process         stop (cannot be caught or ignored)
18    SIGTSTP      stop process         stop signal generated from keyboard
19    SIGCONT      discard signal       continue after stop
20    SIGCHLD      discard signal       child status has changed
21    SIGTTIN      stop process         background read attempted from control terminal
22    SIGTTOU      stop process         background write attempted to control terminal
23    SIGIO        discard signal       I/O is possible on a descriptor (see fcntl(2))
24    SIGXCPU      terminate process    cpu time limit exceeded (see setrlimit(2))
25    SIGXFSZ      terminate process    file size limit exceeded (see setrlimit(2))
26    SIGVTALRM    terminate process    virtual time alarm (see setitimer(2))
27    SIGPROF      terminate process    profiling timer alarm (see setitimer(2))
28    SIGWINCH     discard signal       Window size change
29    SIGINFO      discard signal       status request from keyboard
30    SIGUSR1      terminate process    User defined signal 1
31    SIGUSR2      terminate process    User defined signal 2

*/

#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
pub static ALL_SIGNALS: [&str; 32] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "EMT", "FPE", "KILL", "BUS", "SEGV",
    "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO",
    "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2",
];

pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
    if let Ok(value) = signal_name_or_value.parse() {
        if is_signal(value) {
            return Some(value);
        } else {
            return None;
        }
    }
    let signal_name = signal_name_or_value.trim_start_matches("SIG");

    ALL_SIGNALS.iter().position(|&s| s == signal_name)
}

pub fn is_signal(num: usize) -> bool {
    num < ALL_SIGNALS.len()
}

pub fn signal_name_by_value(signal_value: usize) -> Option<&'static str> {
    ALL_SIGNALS.get(signal_value).copied()
}

#[test]
fn signal_by_value() {
    assert_eq!(signal_by_name_or_value("0"), Some(0));
    for (value, _signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_by_name_or_value(&value.to_string()), Some(value));
    }
}

#[test]
fn signal_by_short_name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_by_name_or_value(signal), Some(value));
    }
}

#[test]
fn signal_by_long_name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(
            signal_by_name_or_value(&format!("SIG{}", signal)),
            Some(value)
        );
    }
}

#[test]
fn name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_name_by_value(value), Some(*signal));
    }
}
<commit_msg>uucore fix NetBSD build.<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Maciej Dziardziel <fiedzia@gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.

// spell-checker:ignore (vars/api) fcntl setrlimit setitimer
// spell-checker:ignore (vars/signals) ABRT ALRM CHLD SEGV SIGABRT SIGALRM SIGBUS SIGCHLD SIGCONT SIGEMT SIGFPE SIGHUP SIGILL SIGINFO SIGINT SIGIO SIGIOT SIGKILL SIGPIPE SIGPROF SIGQUIT SIGSEGV SIGSTOP SIGSYS SIGTERM SIGTRAP SIGTSTP SIGTTIN SIGTTOU SIGURG SIGUSR SIGVTALRM SIGWINCH SIGXCPU SIGXFSZ STKFLT TSTP TTIN TTOU VTALRM XCPU XFSZ

pub static DEFAULT_SIGNAL: usize = 15;

/*

Linux Programmer's Manual

 1 HUP      2 INT      3 QUIT     4 ILL      5 TRAP     6 ABRT     7 BUS
 8 FPE      9 KILL    10 USR1    11 SEGV    12 USR2    13 PIPE    14 ALRM
15 TERM    16 STKFLT  17 CHLD    18 CONT    19 STOP    20 TSTP    21 TTIN
22 TTOU    23 URG     24 XCPU    25 XFSZ    26 VTALRM  27 PROF    28 WINCH
29 POLL    30 PWR     31 SYS

*/

#[cfg(any(target_os = "linux", target_os = "android"))]
pub static ALL_SIGNALS: [&str; 32] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV",
    "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU",
    "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "POLL", "PWR", "SYS",
];

/*

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html

No    Name         Default Action       Description
1     SIGHUP       terminate process    terminal line hangup
2     SIGINT       terminate process    interrupt program
3     SIGQUIT      create core image    quit program
4     SIGILL       create core image    illegal instruction
5     SIGTRAP      create core image    trace trap
6     SIGABRT      create core image    abort program (formerly SIGIOT)
7     SIGEMT       create core image    emulate instruction executed
8     SIGFPE       create core image    floating-point exception
9     SIGKILL      terminate process    kill program
10    SIGBUS       create core image    bus error
11    SIGSEGV      create core image    segmentation violation
12    SIGSYS       create core image    non-existent system call invoked
13    SIGPIPE      terminate process    write on a pipe with no reader
14    SIGALRM      terminate process    real-time timer expired
15    SIGTERM      terminate process    software termination signal
16    SIGURG       discard signal       urgent condition present on socket
17    SIGSTOP      stop process         stop (cannot be caught or ignored)
18    SIGTSTP      stop process         stop signal generated from keyboard
19    SIGCONT      discard signal       continue after stop
20    SIGCHLD      discard signal       child status has changed
21    SIGTTIN      stop process         background read attempted from control terminal
22    SIGTTOU      stop process         background write attempted to control terminal
23    SIGIO        discard signal       I/O is possible on a descriptor (see fcntl(2))
24    SIGXCPU      terminate process    cpu time limit exceeded (see setrlimit(2))
25    SIGXFSZ      terminate process    file size limit exceeded (see setrlimit(2))
26    SIGVTALRM    terminate process    virtual time alarm (see setitimer(2))
27    SIGPROF      terminate process    profiling timer alarm (see setitimer(2))
28    SIGWINCH     discard signal       Window size change
29    SIGINFO      discard signal       status request from keyboard
30    SIGUSR1      terminate process    User defined signal 1
31    SIGUSR2      terminate process    User defined signal 2

*/

#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
pub static ALL_SIGNALS: [&str; 32] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "EMT", "FPE", "KILL", "BUS", "SEGV",
    "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO",
    "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2",
];

/*

     The following signals are defined in NetBSD:

     SIGHUP           1     Hangup
     SIGINT           2     Interrupt
     SIGQUIT          3     Quit
     SIGILL           4     Illegal instruction
     SIGTRAP          5     Trace/BPT trap
     SIGABRT          6     Abort trap
     SIGEMT           7     EMT trap
     SIGFPE           8     Floating point exception
     SIGKILL          9     Killed
     SIGBUS           10    Bus error
     SIGSEGV          11    Segmentation fault
     SIGSYS           12    Bad system call
     SIGPIPE          13    Broken pipe
     SIGALRM          14    Alarm clock
     SIGTERM          15    Terminated
     SIGURG           16    Urgent I/O condition
     SIGSTOP          17    Suspended (signal)
     SIGTSTP          18    Suspended
     SIGCONT          19    Continued
     SIGCHLD          20    Child exited, stopped or continued
     SIGTTIN          21    Stopped (tty input)
     SIGTTOU          22    Stopped (tty output)
     SIGIO            23    I/O possible
     SIGXCPU          24    CPU time limit exceeded
     SIGXFSZ          25    File size limit exceeded
     SIGVTALRM        26    Virtual timer expired
     SIGPROF          27    Profiling timer expired
     SIGWINCH         28    Window size changed
     SIGINFO          29    Information request
     SIGUSR1          30    User defined signal 1
     SIGUSR2          31    User defined signal 2
     SIGPWR           32    Power fail/restart
*/

#[cfg(target_os = "netbsd")]
pub static ALL_SIGNALS: [&str; 33] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "EMT", "FPE", "KILL", "BUS", "SEGV",
    "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO",
    "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2", "PWR"
];

pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
    if let Ok(value) = signal_name_or_value.parse() {
        if is_signal(value) {
            return Some(value);
        } else {
            return None;
        }
    }
    let signal_name = signal_name_or_value.trim_start_matches("SIG");

    ALL_SIGNALS.iter().position(|&s| s == signal_name)
}

pub fn is_signal(num: usize) -> bool {
    num < ALL_SIGNALS.len()
}

pub fn signal_name_by_value(signal_value: usize) -> Option<&'static str> {
    ALL_SIGNALS.get(signal_value).copied()
}

#[test]
fn signal_by_value() {
    assert_eq!(signal_by_name_or_value("0"), Some(0));
    for (value, _signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_by_name_or_value(&value.to_string()), Some(value));
    }
}

#[test]
fn signal_by_short_name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_by_name_or_value(signal), Some(value));
    }
}

#[test]
fn signal_by_long_name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(
            signal_by_name_or_value(&format!("SIG{}", signal)),
            Some(value)
        );
    }
}

#[test]
fn name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_name_by_value(value), Some(*signal));
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use super::*;
use crate::cases::common::{SszStaticType, TestU128, TestU256};
use crate::cases::ssz_static::{check_serialization, check_tree_hash};
use crate::decode::yaml_decode_file;
use serde::{de::Error as SerdeError, Deserialize, Deserializer};
use serde_derive::Deserialize;
use ssz_derive::{Decode, Encode};
use std::fs;
use std::path::{Path, PathBuf};
use tree_hash_derive::TreeHash;
use types::typenum::*;
use types::{BitList, BitVector, FixedVector, VariableList};

#[derive(Debug, Clone, Deserialize)]
struct Metadata {
    root: String,
    signing_root: Option<String>,
}

#[derive(Debug, Clone)]
pub struct SszGeneric {
    path: PathBuf,
    handler_name: String,
    case_name: String,
}

impl LoadCase for SszGeneric {
    fn load_from_dir(path: &Path) -> Result<Self, Error> {
        let components = path
            .components()
            .map(|c| c.as_os_str().to_string_lossy().into_owned())
            .rev()
            .collect::<Vec<_>>();
        // Test case name is last
        let case_name = components[0].clone();
        // Handler name is third last, before suite name and case name
        let handler_name = components[2].clone();
        Ok(Self {
            path: path.into(),
            handler_name,
            case_name,
        })
    }
}

macro_rules! type_dispatch {
    ($function:ident,
     ($($arg:expr),*),
     $base_ty:tt,
     <$($param_ty:ty),*>,
     [ $value:expr => primitive_type ] $($rest:tt)*) => {
        match $value {
            "bool" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* bool>, $($rest)*),
            "uint8" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u8>, $($rest)*),
            "uint16" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u16>, $($rest)*),
            "uint32" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u32>, $($rest)*),
            "uint64" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u64>, $($rest)*),
            "uint128" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* TestU128>, $($rest)*),
            "uint256" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* TestU256>, $($rest)*),
            _ => Err(Error::FailedToParseTest(format!("unsupported: {}", $value))),
        }
    };
    ($function:ident,
     ($($arg:expr),*),
     $base_ty:tt,
     <$($param_ty:ty),*>,
     [ $value:expr => typenum ] $($rest:tt)*) => {
        match $value {
            // DO YOU LIKE NUMBERS?
            "0" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U0>, $($rest)*),
            "1" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U1>, $($rest)*),
            "2" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U2>, $($rest)*),
            "3" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U3>, $($rest)*),
            "4" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U4>, $($rest)*),
            "5" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U5>, $($rest)*),
            "6" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U6>, $($rest)*),
            "7" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U7>, $($rest)*),
            "8" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U8>, $($rest)*),
            "9" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U9>, $($rest)*),
            "16" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U16>, $($rest)*),
            "31" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U31>, $($rest)*),
            "32" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U32>, $($rest)*),
            "64" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U64>, $($rest)*),
            "128" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U128>, $($rest)*),
            "256" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U256>, $($rest)*),
            "512" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U512>, $($rest)*),
            "513" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U513>, $($rest)*),
            "1024" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U1024>, $($rest)*),
            "2048" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U2048>, $($rest)*),
            "4096" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U4096>, $($rest)*),
            "8192" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U8192>, $($rest)*),
            _ => Err(Error::FailedToParseTest(format!("unsupported: {}", $value))),
        }
    };
    ($function:ident,
     ($($arg:expr),*),
     $base_ty:tt,
     <$($param_ty:ty),*>,
     [ $value:expr => test_container ] $($rest:tt)*) => {
        match $value {
            "SingleFieldTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* SingleFieldTestStruct>, $($rest)*),
            "SmallTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* SmallTestStruct>, $($rest)*),
            "FixedTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* FixedTestStruct>, $($rest)*),
            "VarTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* VarTestStruct>, $($rest)*),
            "ComplexTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* ComplexTestStruct>, $($rest)*),
            "BitsStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* BitsStruct>, $($rest)*),
            _ => Err(Error::FailedToParseTest(format!("unsupported: {}", $value))),
        }
    };
    // No base type: apply type params to function
    ($function:ident, ($($arg:expr),*), _, <$($param_ty:ty),*>,) => {
        $function::<$($param_ty),*>($($arg),*)
    };
    ($function:ident, ($($arg:expr),*), $base_type_name:ident, <$($param_ty:ty),*>,) => {
        $function::<$base_type_name<$($param_ty),*>>($($arg),*)
    }
}

impl Case for SszGeneric {
    fn result(&self, _case_index: usize) -> Result<(), Error> {
        let parts = self.case_name.split('_').collect::<Vec<_>>();

        match self.handler_name.as_str() {
            "basic_vector" => {
                let elem_ty = parts[1];
                let length = parts[2];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    FixedVector,
                    <>,
                    [elem_ty => primitive_type]
                    [length => typenum]
                )?;
            }
            "bitlist" => {
                let mut limit = parts[1];

                // Test format is inconsistent, pretend the limit is 32 (arbitrary)
                // https://github.com/ethereum/eth2.0-spec-tests
                if limit == "no" {
                    limit = "32";
                }

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    BitList,
                    <>,
                    [limit => typenum]
                )?;
            }
            "bitvector" => {
                let length = parts[1];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    BitVector,
                    <>,
                    [length => typenum]
                )?;
            }
            "boolean" => {
                ssz_generic_test::<bool>(&self.path)?;
            }
            "uints" => {
                let type_name = "uint".to_owned() + parts[1];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    _,
                    <>,
                    [type_name.as_str() => primitive_type]
                )?;
            }
            "containers" => {
                let type_name = parts[0];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    _,
                    <>,
                    [type_name => test_container]
                )?;
            }
            _ => panic!("unsupported handler: {}", self.handler_name),
        }
        Ok(())
    }
}

fn ssz_generic_test<T: SszStaticType>(path: &Path) -> Result<(), Error> {
    let meta_path = path.join("meta.yaml");
    let meta: Option<Metadata> = if meta_path.is_file() {
        Some(yaml_decode_file(&meta_path)?)
    } else {
        None
    };

    let serialized = fs::read(&path.join("serialized.ssz")).expect("serialized.ssz exists");

    let value_path = path.join("value.yaml");
    let value: Option<T> = if value_path.is_file() {
        Some(yaml_decode_file(&value_path)?)
    } else {
        None
    };

    // Valid
    // TODO: signing root (annoying because of traits)
    if let Some(value) = value {
        check_serialization(&value, &serialized)?;

        if let Some(ref meta) = meta {
            check_tree_hash(&meta.root, value.tree_hash_root())?;
        }
    }
    // Invalid
    else {
        if let Ok(decoded) = T::from_ssz_bytes(&serialized) {
            return Err(Error::DidntFail(format!(
                "Decoded invalid bytes into: {:?}",
                decoded
            )));
        }
    }

    Ok(())
}

// Containers for SSZ generic tests
#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct SingleFieldTestStruct {
    A: u8,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct SmallTestStruct {
    A: u16,
    B: u16,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct FixedTestStruct {
    A: u8,
    B: u64,
    C: u32,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct VarTestStruct {
    A: u16,
    B: VariableList<u16, U1024>,
    C: u8,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct ComplexTestStruct {
    A: u16,
    B: VariableList<u16, U128>,
    C: u8,
    #[serde(deserialize_with = "byte_list_from_hex_str")]
    D: VariableList<u8, U256>,
    E: VarTestStruct,
    F: FixedVector<FixedTestStruct, U4>,
    G: FixedVector<VarTestStruct, U2>,
}

#[derive(Debug, Clone, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct BitsStruct {
    A: BitList<U5>,
    B: BitVector<U2>,
    C: BitVector<U1>,
    D: BitList<U6>,
    E: BitVector<U8>,
}

fn byte_list_from_hex_str<'de, D, N: Unsigned>(
    deserializer: D,
) -> Result<VariableList<u8, N>, D::Error>
where
    D: Deserializer<'de>,
{
    let s: String = Deserialize::deserialize(deserializer)?;
    let decoded: Vec<u8> = hex::decode(&s.as_str()[2..]).map_err(D::Error::custom)?;

    if decoded.len() > N::to_usize() {
        return Err(D::Error::custom(format!(
            "Too many values for list, got: {}, limit: {}",
            decoded.len(),
            N::to_usize()
        )));
    } else {
        Ok(decoded.into())
    }
}
<commit_msg>Fix compile error in ef_tests<commit_after>#![allow(non_snake_case)]

use super::*;
use crate::cases::common::{SszStaticType, TestU128, TestU256};
use crate::cases::ssz_static::{check_serialization, check_tree_hash};
use crate::decode::yaml_decode_file;
use serde::{de::Error as SerdeError, Deserializer};
use serde_derive::Deserialize;
use ssz_derive::{Decode, Encode};
use std::fs;
use std::path::{Path, PathBuf};
use tree_hash_derive::TreeHash;
use types::typenum::*;
use types::{BitList, BitVector, FixedVector, VariableList};

#[derive(Debug, Clone, Deserialize)]
struct Metadata {
    root: String,
    signing_root: Option<String>,
}

#[derive(Debug, Clone)]
pub struct SszGeneric {
    path: PathBuf,
    handler_name: String,
    case_name: String,
}

impl LoadCase for SszGeneric {
    fn load_from_dir(path: &Path) -> Result<Self, Error> {
        let components = path
            .components()
            .map(|c| c.as_os_str().to_string_lossy().into_owned())
            .rev()
            .collect::<Vec<_>>();
        // Test case name is last
        let case_name = components[0].clone();
        // Handler name is third last, before suite name and case name
        let handler_name = components[2].clone();
        Ok(Self {
            path: path.into(),
            handler_name,
            case_name,
        })
    }
}

macro_rules! type_dispatch {
    ($function:ident,
     ($($arg:expr),*),
     $base_ty:tt,
     <$($param_ty:ty),*>,
     [ $value:expr => primitive_type ] $($rest:tt)*) => {
        match $value {
            "bool" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* bool>, $($rest)*),
            "uint8" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u8>, $($rest)*),
            "uint16" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u16>, $($rest)*),
            "uint32" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u32>, $($rest)*),
            "uint64" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* u64>, $($rest)*),
            "uint128" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* TestU128>, $($rest)*),
            "uint256" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* TestU256>, $($rest)*),
            _ => Err(Error::FailedToParseTest(format!("unsupported: {}", $value))),
        }
    };
    ($function:ident,
     ($($arg:expr),*),
     $base_ty:tt,
     <$($param_ty:ty),*>,
     [ $value:expr => typenum ] $($rest:tt)*) => {
        match $value {
            // DO YOU LIKE NUMBERS?
            "0" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U0>, $($rest)*),
            "1" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U1>, $($rest)*),
            "2" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U2>, $($rest)*),
            "3" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U3>, $($rest)*),
            "4" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U4>, $($rest)*),
            "5" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U5>, $($rest)*),
            "6" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U6>, $($rest)*),
            "7" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U7>, $($rest)*),
            "8" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U8>, $($rest)*),
            "9" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U9>, $($rest)*),
            "16" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U16>, $($rest)*),
            "31" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U31>, $($rest)*),
            "32" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U32>, $($rest)*),
            "64" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U64>, $($rest)*),
            "128" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U128>, $($rest)*),
            "256" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U256>, $($rest)*),
            "512" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U512>, $($rest)*),
            "513" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U513>, $($rest)*),
            "1024" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U1024>, $($rest)*),
            "2048" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U2048>, $($rest)*),
            "4096" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U4096>, $($rest)*),
            "8192" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* U8192>, $($rest)*),
            _ => Err(Error::FailedToParseTest(format!("unsupported: {}", $value))),
        }
    };
    ($function:ident,
     ($($arg:expr),*),
     $base_ty:tt,
     <$($param_ty:ty),*>,
     [ $value:expr => test_container ] $($rest:tt)*) => {
        match $value {
            "SingleFieldTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* SingleFieldTestStruct>, $($rest)*),
            "SmallTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* SmallTestStruct>, $($rest)*),
            "FixedTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* FixedTestStruct>, $($rest)*),
            "VarTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* VarTestStruct>, $($rest)*),
            "ComplexTestStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* ComplexTestStruct>, $($rest)*),
            "BitsStruct" => type_dispatch!($function, ($($arg),*), $base_ty, <$($param_ty,)* BitsStruct>, $($rest)*),
            _ => Err(Error::FailedToParseTest(format!("unsupported: {}", $value))),
        }
    };
    // No base type: apply type params to function
    ($function:ident, ($($arg:expr),*), _, <$($param_ty:ty),*>,) => {
        $function::<$($param_ty),*>($($arg),*)
    };
    ($function:ident, ($($arg:expr),*), $base_type_name:ident, <$($param_ty:ty),*>,) => {
        $function::<$base_type_name<$($param_ty),*>>($($arg),*)
    }
}

impl Case for SszGeneric {
    fn result(&self, _case_index: usize) -> Result<(), Error> {
        let parts = self.case_name.split('_').collect::<Vec<_>>();

        match self.handler_name.as_str() {
            "basic_vector" => {
                let elem_ty = parts[1];
                let length = parts[2];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    FixedVector,
                    <>,
                    [elem_ty => primitive_type]
                    [length => typenum]
                )?;
            }
            "bitlist" => {
                let mut limit = parts[1];

                // Test format is inconsistent, pretend the limit is 32 (arbitrary)
                // https://github.com/ethereum/eth2.0-spec-tests
                if limit == "no" {
                    limit = "32";
                }

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    BitList,
                    <>,
                    [limit => typenum]
                )?;
            }
            "bitvector" => {
                let length = parts[1];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    BitVector,
                    <>,
                    [length => typenum]
                )?;
            }
            "boolean" => {
                ssz_generic_test::<bool>(&self.path)?;
            }
            "uints" => {
                let type_name = "uint".to_owned() + parts[1];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    _,
                    <>,
                    [type_name.as_str() => primitive_type]
                )?;
            }
            "containers" => {
                let type_name = parts[0];

                type_dispatch!(
                    ssz_generic_test,
                    (&self.path),
                    _,
                    <>,
                    [type_name => test_container]
                )?;
            }
            _ => panic!("unsupported handler: {}", self.handler_name),
        }
        Ok(())
    }
}

fn ssz_generic_test<T: SszStaticType>(path: &Path) -> Result<(), Error> {
    let meta_path = path.join("meta.yaml");
    let meta: Option<Metadata> = if meta_path.is_file() {
        Some(yaml_decode_file(&meta_path)?)
    } else {
        None
    };

    let serialized = fs::read(&path.join("serialized.ssz")).expect("serialized.ssz exists");

    let value_path = path.join("value.yaml");
    let value: Option<T> = if value_path.is_file() {
        Some(yaml_decode_file(&value_path)?)
    } else {
        None
    };

    // Valid
    // TODO: signing root (annoying because of traits)
    if let Some(value) = value {
        check_serialization(&value, &serialized)?;

        if let Some(ref meta) = meta {
            check_tree_hash(&meta.root, value.tree_hash_root())?;
        }
    }
    // Invalid
    else {
        if let Ok(decoded) = T::from_ssz_bytes(&serialized) {
            return Err(Error::DidntFail(format!(
                "Decoded invalid bytes into: {:?}",
                decoded
            )));
        }
    }

    Ok(())
}

// Containers for SSZ generic tests
#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct SingleFieldTestStruct {
    A: u8,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct SmallTestStruct {
    A: u16,
    B: u16,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct FixedTestStruct {
    A: u8,
    B: u64,
    C: u32,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct VarTestStruct {
    A: u16,
    B: VariableList<u16, U1024>,
    C: u8,
}

#[derive(Debug, Clone, Default, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct ComplexTestStruct {
    A: u16,
    B: VariableList<u16, U128>,
    C: u8,
    #[serde(deserialize_with = "byte_list_from_hex_str")]
    D: VariableList<u8, U256>,
    E: VarTestStruct,
    F: FixedVector<FixedTestStruct, U4>,
    G: FixedVector<VarTestStruct, U2>,
}

#[derive(Debug, Clone, PartialEq, Decode, Encode, TreeHash, Deserialize)]
struct BitsStruct {
    A: BitList<U5>,
    B: BitVector<U2>,
    C: BitVector<U1>,
    D: BitList<U6>,
    E: BitVector<U8>,
}

fn byte_list_from_hex_str<'de, D, N: Unsigned>(
    deserializer: D,
) -> Result<VariableList<u8, N>, D::Error>
where
    D: Deserializer<'de>,
{
    let s: String = serde::de::Deserialize::deserialize(deserializer)?;
    let decoded: Vec<u8> = hex::decode(&s.as_str()[2..]).map_err(D::Error::custom)?;

    if decoded.len() > N::to_usize() {
        return Err(D::Error::custom(format!(
            "Too many values for list, got: {}, limit: {}",
            decoded.len(),
            N::to_usize()
        )));
    } else {
        Ok(decoded.into())
    }
}
<|endoftext|>