├── .formatter.exs ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── issue.yml ├── dependabot.yml └── workflows │ ├── ci-markdown.yml │ ├── ci.yml │ ├── notify.exs │ ├── notify.yml │ ├── ort │ └── action.yml │ ├── release.yml │ └── release_pre_built │ └── action.yml ├── .gitignore ├── .markdownlint.jsonc ├── .ort.yml ├── .ort └── config │ ├── config.yml │ └── evaluator.rules.kts ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── LICENSES ├── Apache-2.0.txt ├── LicenseRef-elixir-trademark-policy.txt └── LicenseRef-scancode-unicode.txt ├── Makefile ├── OPEN_SOURCE_POLICY.md ├── README.md ├── RELEASE.md ├── SECURITY.md ├── VERSION ├── bin ├── elixir ├── elixir.bat ├── elixirc ├── elixirc.bat ├── iex ├── iex.bat ├── mix ├── mix.bat └── mix.ps1 ├── lib ├── eex │ ├── lib │ │ ├── eex.ex │ │ └── eex │ │ │ ├── compiler.ex │ │ │ ├── engine.ex │ │ │ └── smart_engine.ex │ ├── mix.exs │ └── test │ │ ├── eex │ │ ├── smart_engine_test.exs │ │ └── tokenizer_test.exs │ │ ├── eex_test.exs │ │ ├── fixtures │ │ ├── eex_template.eex │ │ ├── eex_template_with_bindings.eex │ │ └── eex_template_with_syntax_error.eex │ │ └── test_helper.exs ├── elixir │ ├── Emakefile │ ├── lib │ │ ├── access.ex │ │ ├── agent.ex │ │ ├── agent │ │ │ └── server.ex │ │ ├── application.ex │ │ ├── atom.ex │ │ ├── base.ex │ │ ├── behaviour.ex │ │ ├── bitwise.ex │ │ ├── calendar.ex │ │ ├── calendar │ │ │ ├── date.ex │ │ │ ├── date_range.ex │ │ │ ├── datetime.ex │ │ │ ├── duration.ex │ │ │ ├── iso.ex │ │ │ ├── naive_datetime.ex │ │ │ ├── time.ex │ │ │ └── time_zone_database.ex │ │ ├── code.ex │ │ ├── code │ │ │ ├── formatter.ex │ │ │ ├── fragment.ex │ │ │ ├── identifier.ex │ │ │ ├── normalizer.ex │ │ │ └── typespec.ex │ │ ├── collectable.ex │ │ ├── config.ex │ │ ├── config │ │ │ ├── provider.ex │ │ │ └── reader.ex │ │ ├── dict.ex │ │ ├── dynamic_supervisor.ex │ │ ├── enum.ex │ │ ├── exception.ex │ │ ├── file.ex │ │ ├── file │ │ │ ├── stat.ex │ │ │ └── stream.ex │ │ ├── float.ex │ │ ├── function.ex │ │ ├── gen_event.ex │ │ ├── gen_event │ │ │ └── stream.ex │ │ ├── gen_server.ex │ │ ├── hash_dict.ex │ │ ├── hash_set.ex │ │ ├── inspect.ex │ │ ├── inspect │ │ │ ├── algebra.ex │ │ │ └── error.ex │ │ ├── integer.ex │ │ ├── io.ex │ │ ├── io │ │ │ ├── ansi.ex │ │ │ ├── ansi │ │ │ │ └── docs.ex │ │ │ └── stream.ex │ │ ├── json.ex │ │ ├── kernel.ex │ │ ├── kernel │ │ │ ├── cli.ex │ │ │ ├── error_handler.ex │ │ │ ├── lexical_tracker.ex │ │ │ ├── parallel_compiler.ex │ │ │ ├── parallel_require.ex │ │ │ ├── special_forms.ex │ │ │ ├── typespec.ex │ │ │ └── utils.ex │ │ ├── keyword.ex │ │ ├── list.ex │ │ ├── list │ │ │ └── chars.ex │ │ ├── macro.ex │ │ ├── macro │ │ │ └── env.ex │ │ ├── map.ex │ │ ├── map_set.ex │ │ ├── module.ex │ │ ├── module │ │ │ ├── behaviour.ex │ │ │ ├── parallel_checker.ex │ │ │ ├── types.ex │ │ │ └── types │ │ │ │ ├── apply.ex │ │ │ │ ├── descr.ex │ │ │ │ ├── expr.ex │ │ │ │ ├── helpers.ex │ │ │ │ ├── of.ex │ │ │ │ └── pattern.ex │ │ ├── node.ex │ │ ├── option_parser.ex │ │ ├── partition_supervisor.ex │ │ ├── path.ex │ │ ├── port.ex │ │ ├── process.ex │ │ ├── protocol.ex │ │ ├── range.ex │ │ ├── record.ex │ │ ├── record │ │ │ └── extractor.ex │ │ ├── regex.ex │ │ ├── registry.ex │ │ ├── set.ex │ │ ├── stream.ex │ │ ├── stream │ │ │ └── reducers.ex │ │ ├── string.ex │ │ ├── string │ │ │ └── chars.ex │ │ ├── string_io.ex │ │ ├── supervisor.ex │ │ ├── supervisor │ │ │ ├── default.ex │ │ │ └── spec.ex │ │ ├── system.ex │ │ ├── task.ex │ │ ├── task │ │ │ ├── supervised.ex │ │ │ └── supervisor.ex │ │ ├── tuple.ex │ │ ├── uri.ex │ │ └── version.ex │ ├── mix.exs │ ├── pages │ │ ├── anti-patterns │ │ │ ├── code-anti-patterns.md │ │ │ ├── design-anti-patterns.md │ │ │ ├── macro-anti-patterns.md │ │ │ ├── process-anti-patterns.md │ │ │ └── what-anti-patterns.md │ │ ├── cheatsheets │ │ │ └── enum-cheat.cheatmd │ │ ├── getting-started │ │ │ ├── alias-require-and-import.md │ │ │ ├── anonymous-functions.md │ │ │ ├── basic-types.md │ │ │ ├── binaries-strings-and-charlists.md │ │ │ ├── case-cond-and-if.md │ │ │ ├── comprehensions.md │ │ │ ├── debugging.md │ │ │ ├── enumerable-and-streams.md │ │ │ ├── erlang-libraries.md │ │ │ ├── introduction.md │ │ │ ├── io-and-the-file-system.md │ │ │ ├── keywords-and-maps.md │ │ │ ├── lists-and-tuples.md │ │ │ ├── module-attributes.md │ │ │ ├── modules-and-functions.md │ │ │ ├── optional-syntax.md │ │ │ ├── pattern-matching.md │ │ │ ├── processes.md │ │ │ ├── protocols.md │ │ │ ├── recursion.md │ │ │ ├── sigils.md │ │ │ ├── structs.md │ │ │ ├── try-catch-and-rescue.md │ │ │ └── writing-documentation.md │ │ ├── images │ │ │ ├── kv-observer.png │ │ │ └── logo.png │ │ ├── meta-programming │ │ │ ├── domain-specific-languages.md │ │ │ ├── macros.md │ │ │ └── quote-and-unquote.md │ │ ├── mix-and-otp │ │ │ ├── agents.md │ │ │ ├── config-and-releases.md │ │ │ ├── dependencies-and-umbrella-projects.md │ │ │ ├── distributed-tasks.md │ │ │ ├── docs-tests-and-with.md │ │ │ ├── dynamic-supervisor.md │ │ │ ├── erlang-term-storage.md │ │ │ ├── genservers.md │ │ │ ├── introduction-to-mix.md │ │ │ ├── supervisor-and-application.md │ │ │ └── task-and-gen-tcp.md │ │ └── references │ │ │ ├── compatibility-and-deprecations.md │ │ │ ├── gradual-set-theoretic-types.md │ │ │ ├── library-guidelines.md │ │ │ ├── naming-conventions.md │ │ │ ├── operators.md │ │ │ ├── patterns-and-guards.md │ │ │ ├── syntax-reference.md │ │ │ ├── typespecs.md │ │ │ └── unicode-syntax.md │ ├── scripts │ │ ├── cover.exs │ │ ├── cover_record.exs │ │ ├── diff.exs │ │ ├── docs_config.exs │ │ ├── elixir_docs.exs │ │ ├── generate_app.escript │ │ ├── mix_docs.exs │ │ └── windows_installer │ │ │ ├── .gitignore │ │ │ ├── assets │ │ │ └── Elixir.ico │ │ │ ├── build.sh │ │ │ ├── installer.nsi │ │ │ └── update_system_path.erl │ ├── src │ │ ├── elixir.app.src │ │ ├── elixir.erl │ │ ├── elixir.hrl │ │ ├── elixir_aliases.erl │ │ ├── elixir_bitstring.erl │ │ ├── elixir_bootstrap.erl │ │ ├── elixir_clauses.erl │ │ ├── elixir_code_server.erl │ │ ├── elixir_compiler.erl │ │ ├── elixir_config.erl │ │ ├── elixir_def.erl │ │ ├── elixir_dispatch.erl │ │ ├── elixir_env.erl │ │ ├── elixir_erl.erl │ │ ├── elixir_erl_clauses.erl │ │ ├── elixir_erl_compiler.erl │ │ ├── elixir_erl_for.erl │ │ ├── elixir_erl_pass.erl │ │ ├── elixir_erl_try.erl │ │ ├── elixir_erl_var.erl │ │ ├── elixir_errors.erl │ │ ├── elixir_expand.erl │ │ ├── elixir_fn.erl │ │ ├── elixir_import.erl │ │ ├── elixir_interpolation.erl │ │ ├── elixir_json.erl │ │ ├── elixir_lexical.erl │ │ ├── elixir_map.erl │ │ ├── elixir_module.erl │ │ ├── elixir_overridable.erl │ │ ├── elixir_parser.yrl │ │ ├── elixir_quote.erl │ │ ├── elixir_rewrite.erl │ │ ├── elixir_sup.erl │ │ ├── elixir_tokenizer.erl │ │ ├── elixir_tokenizer.hrl │ │ ├── elixir_utils.erl │ │ └── iex.erl │ ├── test │ │ ├── elixir │ │ │ ├── access_test.exs │ │ │ ├── agent_test.exs │ │ │ ├── application_test.exs │ │ │ ├── atom_test.exs │ │ │ ├── base_test.exs │ │ │ ├── bitwise_test.exs │ │ │ ├── calendar │ │ │ │ ├── date_range_test.exs │ │ │ │ ├── date_test.exs │ │ │ │ ├── datetime_test.exs │ │ │ │ ├── duration_test.exs │ │ │ │ ├── fakes.exs │ │ │ │ ├── holocene.exs │ │ │ │ ├── iso_test.exs │ │ │ │ ├── naive_datetime_test.exs │ │ │ │ └── time_test.exs │ │ │ ├── calendar_test.exs │ │ │ ├── changelog_test.exs │ │ │ ├── code_formatter │ │ │ │ ├── calls_test.exs │ │ │ │ ├── comments_test.exs │ │ │ │ ├── containers_test.exs │ │ │ │ ├── general_test.exs │ │ │ │ ├── integration_test.exs │ │ │ │ ├── literals_test.exs │ │ │ │ ├── migration_test.exs │ │ │ │ └── operators_test.exs │ │ │ ├── code_fragment_test.exs │ │ │ ├── code_identifier_test.exs │ │ │ ├── code_normalizer │ │ │ │ ├── formatted_ast_test.exs │ │ │ │ └── quoted_ast_test.exs │ │ │ ├── code_test.exs │ │ │ ├── collectable_test.exs │ │ │ ├── config │ │ │ │ ├── provider_test.exs │ │ │ │ └── reader_test.exs │ │ │ ├── config_test.exs │ │ │ ├── dynamic_supervisor_test.exs │ │ │ ├── enum_test.exs │ │ │ ├── exception_test.exs │ │ │ ├── file │ │ │ │ └── stream_test.exs │ │ │ ├── file_test.exs │ │ │ ├── fixtures │ │ │ │ ├── at_exit.exs │ │ │ │ ├── code_sample.exs │ │ │ │ ├── compile_sample.ex │ │ │ │ ├── configs │ │ │ │ │ ├── bad_app.exs │ │ │ │ │ ├── bad_import.exs │ │ │ │ │ ├── env.exs │ │ │ │ │ ├── good_config.exs │ │ │ │ │ ├── good_import.exs │ │ │ │ │ ├── good_kw.exs │ │ │ │ │ ├── imports_recursive.exs │ │ │ │ │ ├── kernel.exs │ │ │ │ │ ├── nested.exs │ │ │ │ │ └── recursive.exs │ │ │ │ ├── consolidation │ │ │ │ │ ├── no_impl.ex │ │ │ │ │ ├── sample.ex │ │ │ │ │ └── with_any.ex │ │ │ │ ├── cp_mode │ │ │ │ ├── cp_r │ │ │ │ │ ├── a │ │ │ │ │ │ ├── 1.txt │ │ │ │ │ │ └── a │ │ │ │ │ │ │ └── 2.txt │ │ │ │ │ └── b │ │ │ │ │ │ └── 3.txt │ │ │ │ ├── dialyzer │ │ │ │ │ ├── assertions.ex │ │ │ │ │ ├── boolean_check.ex │ │ │ │ │ ├── callback.ex │ │ │ │ │ ├── cond.ex │ │ │ │ │ ├── defmacrop.ex │ │ │ │ │ ├── for_bitstring.ex │ │ │ │ │ ├── for_boolean_check.ex │ │ │ │ │ ├── is_struct.ex │ │ │ │ │ ├── macrocallback.ex │ │ │ │ │ ├── raise.ex │ │ │ │ │ ├── remote_call.ex │ │ │ │ │ ├── rewrite.ex │ │ │ │ │ ├── try.ex │ │ │ │ │ ├── with.ex │ │ │ │ │ ├── with_no_return.ex │ │ │ │ │ └── with_throwing_else.ex │ │ │ │ ├── file.bin │ │ │ │ ├── file.txt │ │ │ │ ├── multiline_file.txt │ │ │ │ ├── utf16_be_bom.txt │ │ │ │ ├── utf16_le_bom.txt │ │ │ │ ├── utf8.txt │ │ │ │ └── utf8_bom.txt │ │ │ ├── float_test.exs │ │ │ ├── function_test.exs │ │ │ ├── gen_server_test.exs │ │ │ ├── inspect │ │ │ │ └── algebra_test.exs │ │ │ ├── inspect_test.exs │ │ │ ├── integer_test.exs │ │ │ ├── io │ │ │ │ ├── ansi │ │ │ │ │ └── docs_test.exs │ │ │ │ └── ansi_test.exs │ │ │ ├── io_test.exs │ │ │ ├── json_test.exs │ │ │ ├── kernel │ │ │ │ ├── alias_test.exs │ │ │ │ ├── binary_test.exs │ │ │ │ ├── charlist_test.exs │ │ │ │ ├── cli_test.exs │ │ │ │ ├── comprehension_test.exs │ │ │ │ ├── defaults_test.exs │ │ │ │ ├── deprecated_test.exs │ │ │ │ ├── diagnostics_test.exs │ │ │ │ ├── dialyzer_test.exs │ │ │ │ ├── docs_test.exs │ │ │ │ ├── errors_test.exs │ │ │ │ ├── expansion_test.exs │ │ │ │ ├── fn_test.exs │ │ │ │ ├── guard_test.exs │ │ │ │ ├── impl_test.exs │ │ │ │ ├── import_test.exs │ │ │ │ ├── lexical_tracker_test.exs │ │ │ │ ├── macros_test.exs │ │ │ │ ├── overridable_test.exs │ │ │ │ ├── parallel_compiler_test.exs │ │ │ │ ├── parser_test.exs │ │ │ │ ├── quote_test.exs │ │ │ │ ├── raise_test.exs │ │ │ │ ├── sigils_test.exs │ │ │ │ ├── special_forms_test.exs │ │ │ │ ├── string_tokenizer_test.exs │ │ │ │ ├── tracers_test.exs │ │ │ │ ├── warning_test.exs │ │ │ │ └── with_test.exs │ │ │ ├── kernel_test.exs │ │ │ ├── keyword_test.exs │ │ │ ├── list │ │ │ │ └── chars_test.exs │ │ │ ├── list_test.exs │ │ │ ├── macro │ │ │ │ └── env_test.exs │ │ │ ├── macro_test.exs │ │ │ ├── map_set_test.exs │ │ │ ├── map_test.exs │ │ │ ├── module │ │ │ │ └── types │ │ │ │ │ ├── descr_test.exs │ │ │ │ │ ├── expr_test.exs │ │ │ │ │ ├── helpers_test.exs │ │ │ │ │ ├── infer_test.exs │ │ │ │ │ ├── integration_test.exs │ │ │ │ │ ├── pattern_test.exs │ │ │ │ │ └── type_helper.exs │ │ │ ├── module_test.exs │ │ │ ├── option_parser_test.exs │ │ │ ├── partition_supervisor_test.exs │ │ │ ├── path_test.exs │ │ │ ├── port_test.exs │ │ │ ├── process_test.exs │ │ │ ├── protocol │ │ │ │ └── consolidation_test.exs │ │ │ ├── protocol_test.exs │ │ │ ├── range_test.exs │ │ │ ├── record_test.exs │ │ │ ├── regex_test.exs │ │ │ ├── registry_test.exs │ │ │ ├── stream_test.exs │ │ │ ├── string │ │ │ │ └── chars_test.exs │ │ │ ├── string_io_test.exs │ │ │ ├── string_test.exs │ │ │ ├── supervisor_test.exs │ │ │ ├── system_test.exs │ │ │ ├── task │ │ │ │ └── supervisor_test.exs │ │ │ ├── task_test.exs │ │ │ ├── test_helper.exs │ │ │ ├── tuple_test.exs │ │ │ ├── typespec_test.exs │ │ │ ├── uri_test.exs │ │ │ └── version_test.exs │ │ └── erlang │ │ │ ├── atom_test.erl │ │ │ ├── control_test.erl │ │ │ ├── function_test.erl │ │ │ ├── string_test.erl │ │ │ ├── test_helper.erl │ │ │ └── tokenizer_test.erl │ └── unicode │ │ ├── IdentifierType.txt │ │ ├── PropList.txt │ │ ├── PropertyValueAliases.txt │ │ ├── ScriptExtensions.txt │ │ ├── Scripts.txt │ │ ├── SpecialCasing.txt │ │ ├── UnicodeData.txt │ │ ├── confusables.txt │ │ ├── security.ex │ │ ├── tokenizer.ex │ │ └── unicode.ex ├── ex_unit │ ├── examples │ │ ├── difference.exs │ │ └── one_of_each.exs │ ├── lib │ │ ├── ex_unit.ex │ │ └── ex_unit │ │ │ ├── assertions.ex │ │ │ ├── callbacks.ex │ │ │ ├── capture_io.ex │ │ │ ├── capture_log.ex │ │ │ ├── capture_server.ex │ │ │ ├── case.ex │ │ │ ├── case_template.ex │ │ │ ├── cli_formatter.ex │ │ │ ├── diff.ex │ │ │ ├── doc_test.ex │ │ │ ├── event_manager.ex │ │ │ ├── failures_manifest.ex │ │ │ ├── filters.ex │ │ │ ├── formatter.ex │ │ │ ├── on_exit_handler.ex │ │ │ ├── on_exit_handler │ │ │ └── supervisor.ex │ │ │ ├── runner.ex │ │ │ ├── runner_stats.ex │ │ │ └── server.ex │ ├── mix.exs │ └── test │ │ ├── ex_unit │ │ ├── assertions_test.exs │ │ ├── callbacks_test.exs │ │ ├── capture_io_test.exs │ │ ├── capture_log_test.exs │ │ ├── case_template_test.exs │ │ ├── case_test.exs │ │ ├── describe_test.exs │ │ ├── diff_test.exs │ │ ├── doc_test_test.exs │ │ ├── failures_manifest_test.exs │ │ ├── filters_test.exs │ │ ├── formatter_test.exs │ │ ├── register_test.exs │ │ ├── runner_stats_test.exs │ │ └── supervised_test.exs │ │ ├── ex_unit_test.exs │ │ ├── fixtures │ │ ├── failing.md │ │ └── passing.md │ │ └── test_helper.exs ├── iex │ ├── lib │ │ ├── iex.ex │ │ └── iex │ │ │ ├── app.ex │ │ │ ├── autocomplete.ex │ │ │ ├── broker.ex │ │ │ ├── config.ex │ │ │ ├── evaluator.ex │ │ │ ├── helpers.ex │ │ │ ├── history.ex │ │ │ ├── info.ex │ │ │ ├── introspection.ex │ │ │ ├── mix_listener.ex │ │ │ ├── pry.ex │ │ │ └── server.ex │ ├── mix.exs │ └── test │ │ ├── iex │ │ ├── autocomplete_test.exs │ │ ├── config_test.exs │ │ ├── helpers_test.exs │ │ ├── info_test.exs │ │ ├── interaction_test.exs │ │ ├── pry_test.exs │ │ └── server_test.exs │ │ └── test_helper.exs ├── logger │ ├── lib │ │ ├── logger.ex │ │ └── logger │ │ │ ├── app.ex │ │ │ ├── backends │ │ │ ├── config.ex │ │ │ ├── console.ex │ │ │ ├── handler.ex │ │ │ ├── internal.ex │ │ │ ├── supervisor.ex │ │ │ └── watcher.ex │ │ │ ├── formatter.ex │ │ │ ├── translator.ex │ │ │ └── utils.ex │ ├── mix.exs │ └── test │ │ ├── logger │ │ ├── backends │ │ │ ├── console_test.exs │ │ │ └── handler_test.exs │ │ ├── backends_test.exs │ │ ├── formatter_test.exs │ │ ├── translator_test.exs │ │ └── utils_test.exs │ │ ├── logger_test.exs │ │ └── test_helper.exs └── mix │ ├── lib │ ├── mix.ex │ └── mix │ │ ├── app_loader.ex │ │ ├── cli.ex │ │ ├── compilers │ │ ├── elixir.ex │ │ ├── erlang.ex │ │ ├── protocol.ex │ │ └── test.ex │ │ ├── config.ex │ │ ├── dep.ex │ │ ├── dep │ │ ├── converger.ex │ │ ├── elixir_scm.ex │ │ ├── fetcher.ex │ │ ├── loader.ex │ │ ├── lock.ex │ │ └── umbrella.ex │ │ ├── exceptions.ex │ │ ├── generator.ex │ │ ├── hex.ex │ │ ├── local.ex │ │ ├── local │ │ └── installer.ex │ │ ├── project.ex │ │ ├── project_stack.ex │ │ ├── pubsub.ex │ │ ├── pubsub │ │ └── subscriber.ex │ │ ├── rebar.ex │ │ ├── release.ex │ │ ├── remote_converger.ex │ │ ├── scm.ex │ │ ├── scm │ │ ├── git.ex │ │ └── path.ex │ │ ├── shell.ex │ │ ├── shell │ │ ├── io.ex │ │ ├── process.ex │ │ └── quiet.ex │ │ ├── state.ex │ │ ├── sync │ │ ├── lock.ex │ │ └── pubsub.ex │ │ ├── task.compiler.ex │ │ ├── task.ex │ │ ├── tasks │ │ ├── app.config.ex │ │ ├── app.start.ex │ │ ├── app.tree.ex │ │ ├── archive.build.ex │ │ ├── archive.check.ex │ │ ├── archive.ex │ │ ├── archive.install.ex │ │ ├── archive.uninstall.ex │ │ ├── clean.ex │ │ ├── cmd.ex │ │ ├── compile.all.ex │ │ ├── compile.app.ex │ │ ├── compile.elixir.ex │ │ ├── compile.erlang.ex │ │ ├── compile.ex │ │ ├── compile.leex.ex │ │ ├── compile.protocols.ex │ │ ├── compile.yecc.ex │ │ ├── deps.clean.ex │ │ ├── deps.compile.ex │ │ ├── deps.ex │ │ ├── deps.get.ex │ │ ├── deps.loadpaths.ex │ │ ├── deps.partition.ex │ │ ├── deps.precompile.ex │ │ ├── deps.tree.ex │ │ ├── deps.unlock.ex │ │ ├── deps.update.ex │ │ ├── do.ex │ │ ├── escript.build.ex │ │ ├── escript.ex │ │ ├── escript.install.ex │ │ ├── escript.uninstall.ex │ │ ├── eval.ex │ │ ├── format.ex │ │ ├── help.ex │ │ ├── iex.ex │ │ ├── loadconfig.ex │ │ ├── loadpaths.ex │ │ ├── local.ex │ │ ├── local.hex.ex │ │ ├── local.rebar.ex │ │ ├── new.ex │ │ ├── profile.cprof.ex │ │ ├── profile.eprof.ex │ │ ├── profile.fprof.ex │ │ ├── profile.tprof.ex │ │ ├── release.ex │ │ ├── release.init.ex │ │ ├── run.ex │ │ ├── test.coverage.ex │ │ ├── test.ex │ │ ├── will_recompile.ex │ │ └── xref.ex │ │ ├── tasks_server.ex │ │ └── utils.ex │ ├── mix.exs │ └── test │ ├── fixtures │ ├── .gitignore │ ├── archive │ │ ├── invalid-archive-0.1.0.ez │ │ ├── lib │ │ │ └── local.sample.ex │ │ └── priv │ │ │ ├── .dot_file │ │ │ └── not_really_an.so │ ├── compile_erlang │ │ ├── include │ │ │ └── r.hrl │ │ └── src │ │ │ ├── b.erl │ │ │ └── c.erl │ ├── compile_leex │ │ └── src │ │ │ └── test_ok.xrl │ ├── compile_listeners │ │ └── deps │ │ │ └── reloader │ │ │ ├── lib │ │ │ └── reloader.ex │ │ │ └── mix.exs │ ├── compile_yecc │ │ └── src │ │ │ └── test_ok.yrl │ ├── config.exs │ ├── deps_cycle │ │ ├── app1 │ │ │ └── mix.exs │ │ └── app2 │ │ │ └── mix.exs │ ├── deps_status │ │ ├── _build │ │ │ └── dev │ │ │ │ └── lib │ │ │ │ ├── invalidapp │ │ │ │ └── ebin │ │ │ │ │ └── invalidapp.app │ │ │ │ ├── invalidvsn │ │ │ │ └── ebin │ │ │ │ │ └── invalidvsn.app │ │ │ │ ├── nosemver │ │ │ │ └── ebin │ │ │ │ │ └── nosemver.app │ │ │ │ └── ok │ │ │ │ └── ebin │ │ │ │ └── ok.app │ │ ├── custom │ │ │ ├── bad_deps_repo │ │ │ │ └── mix.exs │ │ │ ├── deps_repo │ │ │ │ └── mix.exs │ │ │ ├── noscm_repo │ │ │ │ └── mix.exs │ │ │ └── raw_repo │ │ │ │ ├── lib │ │ │ │ └── raw_repo.ex │ │ │ │ └── mix.exs │ │ └── deps │ │ │ ├── invalidapp │ │ │ └── mix.exs │ │ │ ├── invalidvsn │ │ │ └── .gitkeep │ │ │ ├── nosemver │ │ │ └── .gitkeep │ │ │ └── ok │ │ │ ├── mix.exs │ │ │ └── priv │ │ │ └── sample │ ├── escript_test │ │ ├── config │ │ │ └── config.exs │ │ ├── lib │ │ │ └── escript_test.ex │ │ ├── priv │ │ │ └── hello │ │ │ │ └── world.txt │ │ └── src │ │ │ └── escript_test.erl │ ├── no_mixfile │ │ └── lib │ │ │ ├── a.ex │ │ │ └── b.ex │ ├── rebar3 │ ├── rebar_dep │ │ ├── rebar.config │ │ ├── rebar.config.script │ │ └── src │ │ │ ├── rebar_dep.app.src │ │ │ └── rebar_dep.erl │ ├── rebar_dep_script │ │ ├── rebar.config │ │ └── rebar.config.script │ ├── rebar_override │ │ └── rebar.config.script │ ├── release_test │ │ ├── config │ │ │ └── config.exs │ │ ├── lib │ │ │ └── release_test.ex │ │ ├── mix.exs │ │ └── priv │ │ │ └── hello │ ├── test_failed │ │ ├── mix.exs │ │ └── test │ │ │ ├── only_failing_test_failed.exs │ │ │ ├── only_passing_test_failed.exs │ │ │ ├── passing_and_failing_test_failed.exs │ │ │ └── test_helper.exs │ ├── test_stale │ │ ├── lib │ │ │ ├── a.ex │ │ │ └── b.ex │ │ ├── mix.exs │ │ └── test │ │ │ ├── a_test_stale.exs │ │ │ ├── b_test_stale.exs │ │ │ └── test_helper.exs │ ├── umbrella_dep │ │ ├── deps │ │ │ └── umbrella │ │ │ │ ├── apps │ │ │ │ ├── bar │ │ │ │ │ ├── lib │ │ │ │ │ │ └── bar.ex │ │ │ │ │ └── mix.exs │ │ │ │ ├── dont_error_on_files │ │ │ │ ├── dont_error_on_missing_mixfile │ │ │ │ │ └── .gitkeep │ │ │ │ └── foo │ │ │ │ │ ├── lib │ │ │ │ │ └── foo.ex │ │ │ │ │ └── mix.exs │ │ │ │ └── mix.exs │ │ └── mix.exs │ └── umbrella_test │ │ ├── apps │ │ ├── bar │ │ │ ├── lib │ │ │ │ └── bar.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ │ ├── bar_tests.exs │ │ │ │ └── test_helper.exs │ │ └── foo │ │ │ ├── lib │ │ │ └── foo.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ ├── foo_tests.exs │ │ │ └── test_helper.exs │ │ └── mix.exs │ ├── mix │ ├── aliases_test.exs │ ├── cli_test.exs │ ├── dep │ │ ├── converger_test.exs │ │ └── lock_test.exs │ ├── dep_test.exs │ ├── generator_test.exs │ ├── local │ │ └── installer_test.exs │ ├── local_test.exs │ ├── project_test.exs │ ├── rebar_test.exs │ ├── release_test.exs │ ├── scm │ │ └── git_test.exs │ ├── scm_test.exs │ ├── shell │ │ ├── io_test.exs │ │ └── quiet_test.exs │ ├── shell_test.exs │ ├── sync │ │ ├── lock_test.exs │ │ └── pubsub_test.exs │ ├── task_test.exs │ ├── tasks │ │ ├── app.config_test.exs │ │ ├── app.start_test.exs │ │ ├── app.tree_test.exs │ │ ├── archive_test.exs │ │ ├── clean_test.exs │ │ ├── cmd_test.exs │ │ ├── compile.app_test.exs │ │ ├── compile.elixir_test.exs │ │ ├── compile.erlang_test.exs │ │ ├── compile.leex_test.exs │ │ ├── compile.yecc_test.exs │ │ ├── compile_test.exs │ │ ├── deps.git_test.exs │ │ ├── deps.path_test.exs │ │ ├── deps.tree_test.exs │ │ ├── deps_test.exs │ │ ├── do_test.exs │ │ ├── escript_test.exs │ │ ├── eval_test.exs │ │ ├── format_test.exs │ │ ├── help_test.exs │ │ ├── iex_test.exs │ │ ├── loadconfig_test.exs │ │ ├── local_test.exs │ │ ├── new_test.exs │ │ ├── profile.cprof_test.exs │ │ ├── profile.eprof_test.exs │ │ ├── profile.fprof_test.exs │ │ ├── profile.tprof_test.exs │ │ ├── release.init_test.exs │ │ ├── release_test.exs │ │ ├── run_test.exs │ │ ├── test_test.exs │ │ ├── will_recompile_test.exs │ │ └── xref_test.exs │ ├── umbrella_test.exs │ └── utils_test.exs │ ├── mix_test.exs │ └── test_helper.exs ├── man ├── common ├── elixir.1.in ├── elixirc.1 ├── iex.1.in └── mix.1 └── project.spdx.yml /.formatter.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | [ 6 | inputs: [ 7 | "lib/*/{lib,scripts,unicode,test}/**/*.{ex,exs}", 8 | "lib/*/*.exs", 9 | "lib/ex_unit/examples/*.exs", 10 | ".formatter.exs" 11 | ], 12 | locals_without_parens: [ 13 | # Formatter tests 14 | assert_format: 2, 15 | assert_format: 3, 16 | assert_same: 1, 17 | assert_same: 2, 18 | 19 | # Errors tests 20 | assert_eval_raise: 3, 21 | 22 | # Float tests 23 | float_assert: 1 24 | ] 25 | ] 26 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | lib/elixir/test/elixir/fixtures/*.txt text eol=lf 6 | *.ex diff=elixir 7 | *.exs diff=elixir 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | --- 5 | blank_issues_enabled: true 6 | 7 | contact_links: 8 | - name: Ask questions, support, and general discussions 9 | url: https://elixirforum.com/ 10 | about: Ask questions, provide support, and more on Elixir Forum 11 | 12 | - name: Propose new features 13 | url: https://github.com/elixir-lang/elixir/#proposing-new-features 14 | about: Propose new features in our mailing list 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | --- 5 | name: Report an issue 6 | description: 7 | Tell us about something that is not working the way we (probably) intend 8 | body: 9 | - type: markdown 10 | attributes: 11 | value: > 12 | Thank you for contributing to Elixir! :heart: 13 | 14 | 15 | Please, do not use this form for guidance, questions or support. 16 | Try instead in [Elixir Forum](https://elixirforum.com), 17 | the [IRC Chat](https://web.libera.chat/#elixir), 18 | [Stack Overflow](https://stackoverflow.com/questions/tagged/elixir), 19 | [Slack](https://elixir-slackin.herokuapp.com), 20 | [Discord](https://discord.gg/elixir) or in other online communities. 21 | 22 | - type: textarea 23 | id: elixir-and-otp-version 24 | attributes: 25 | label: Elixir and Erlang/OTP versions 26 | description: Paste the output of `elixir --version` here. 27 | validations: 28 | required: true 29 | 30 | - type: input 31 | id: os 32 | attributes: 33 | label: Operating system 34 | description: The operating system that this issue is happening on. 35 | validations: 36 | required: true 37 | 38 | - type: textarea 39 | id: current-behavior 40 | attributes: 41 | label: Current behavior 42 | description: > 43 | Include code samples, errors, and stacktraces if appropriate. 44 | 45 | 46 | If reporting a bug, please include the reproducing steps. 47 | validations: 48 | required: true 49 | 50 | - type: textarea 51 | id: expected-behavior 52 | attributes: 53 | label: Expected behavior 54 | description: A short description on how you expect the code to behave. 55 | validations: 56 | required: true 57 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | interval: "weekly" 10 | -------------------------------------------------------------------------------- /.github/workflows/ci-markdown.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | name: CI for Markdown content 5 | 6 | on: 7 | push: 8 | branches: 9 | - "main" 10 | paths: 11 | - "lib/**/*.md" 12 | pull_request: 13 | paths: 14 | - "lib/**/*.md" 15 | workflow_dispatch: 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | lint: 22 | name: Lint Markdown content 23 | 24 | strategy: 25 | fail-fast: false 26 | 27 | runs-on: ubuntu-latest 28 | 29 | steps: 30 | - name: Check out the repository 31 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 32 | with: 33 | fetch-depth: 10 34 | 35 | - name: Run markdownlint 36 | uses: DavidAnson/markdownlint-cli2-action@992badcdf24e3b8eb7e87ff9287fe931bcb00c6e # v20.0.0 37 | with: 38 | globs: | 39 | lib/elixir/pages/**/*.md 40 | README.md 41 | -------------------------------------------------------------------------------- /.github/workflows/notify.exs: -------------------------------------------------------------------------------- 1 | # #!/usr/bin/env elixir 2 | 3 | # SPDX-License-Identifier: Apache-2.0 4 | # SPDX-FileCopyrightText: 2021 The Elixir Team 5 | 6 | [tag] = System.argv() 7 | 8 | Mix.install([ 9 | {:req, "~> 0.2.1"}, 10 | {:jason, "~> 1.0"} 11 | ]) 12 | 13 | %{status: 200, body: release} = 14 | Req.get!("https://api.github.com/repos/elixir-lang/elixir/releases/tags/#{tag}") 15 | 16 | if release["draft"] do 17 | raise "cannot notify a draft release" 18 | end 19 | 20 | ## Notify on elixir-lang-ann 21 | 22 | names_and_checksums = 23 | for asset <- release["assets"], 24 | name = asset["name"], 25 | name =~ ~r/.sha\d+sum$/, 26 | do: {name, Req.get!(asset["browser_download_url"]).body} 27 | 28 | line_items = 29 | for {name, checksum_and_name} <- Enum.sort(names_and_checksums) do 30 | [checksum | _] = String.split(checksum_and_name, " ") 31 | root = Path.rootname(name) 32 | "." <> type = Path.extname(name) 33 | " * #{root} - #{type} - #{checksum}\n" 34 | end 35 | 36 | body = "https://github.com/elixir-lang/elixir/releases/tag/#{tag}\n\n#{line_items}" 37 | 38 | IO.puts([ 39 | "========================================\n", 40 | body, 41 | "\n========================================" 42 | ]) 43 | 44 | mail = %{ 45 | # The email must have access to post 46 | "From" => "jose.valim@dashbit.co", 47 | "To" => "elixir-lang-ann@googlegroups.com", 48 | "Subject" => "Elixir #{tag} released", 49 | "HtmlBody" => body, 50 | "MessageStream" => "outbound" 51 | } 52 | 53 | unless System.get_env("DRYRUN") do 54 | headers = %{ 55 | "X-Postmark-Server-Token" => System.fetch_env!("ELIXIR_LANG_ANN_TOKEN") 56 | } 57 | 58 | resp = Req.post!("https://api.postmarkapp.com/email", {:json, mail}, headers: headers) 59 | IO.puts("#{resp.status} elixir-lang-ann\n#{inspect(resp.body)}") 60 | end 61 | 62 | ## Notify on Elixir Forum 63 | 64 | post = %{ 65 | "title" => "Elixir #{tag} released", 66 | "raw" => "https://github.com/elixir-lang/elixir/releases/tag/#{tag}\n\n#{release["body"]}", 67 | # Elixir News 68 | "category" => 28 69 | } 70 | 71 | unless System.get_env("DRYRUN") do 72 | headers = %{ 73 | "api-key" => System.fetch_env!("ELIXIR_FORUM_TOKEN"), 74 | "api-username" => "Elixir" 75 | } 76 | 77 | resp = Req.post!("https://elixirforum.com/posts.json", {:json, post}, headers: headers) 78 | IO.puts("#{resp.status} Elixir Forum\n#{inspect(resp.body)}") 79 | end 80 | -------------------------------------------------------------------------------- /.github/workflows/notify.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | name: Notify 5 | 6 | on: 7 | release: 8 | types: 9 | - published 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | notify: 16 | runs-on: ubuntu-latest 17 | name: Notify 18 | steps: 19 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 20 | with: 21 | fetch-depth: 50 22 | - uses: erlef/setup-beam@8aa8a857c6be0daae6e97272bb299d5b942675a4 # v1.19.0 23 | with: 24 | otp-version: "27.3" 25 | elixir-version: "1.18.3" 26 | - name: Run Elixir script 27 | env: 28 | ELIXIR_FORUM_TOKEN: ${{ secrets.ELIXIR_FORUM_TOKEN }} 29 | ELIXIR_LANG_ANN_TOKEN: ${{ secrets.ELIXIR_LANG_ANN_TOKEN }} 30 | run: | 31 | elixir .github/workflows/notify.exs ${{ github.ref_name }} 32 | -------------------------------------------------------------------------------- /.github/workflows/release_pre_built/action.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | name: "Release pre built" 5 | description: "Builds elixir release, ExDoc and generates docs" 6 | inputs: 7 | otp: 8 | description: "The major OTP version" 9 | otp_version: 10 | description: "The exact OTP version (major.minor[.patch])" 11 | build_docs: 12 | description: "If docs have to be built or not" 13 | runs: 14 | using: "composite" 15 | steps: 16 | - uses: erlef/setup-beam@5304e04ea2b355f03681464e683d92e3b2f18451 # v1.18.2 17 | with: 18 | otp-version: ${{ inputs.otp_version }} 19 | version-type: strict 20 | - name: Build Elixir Release 21 | shell: bash 22 | run: | 23 | make Precompiled.zip 24 | mv Precompiled.zip elixir-otp-${{ inputs.otp }}.zip 25 | echo "$PWD/bin" >> $GITHUB_PATH 26 | - name: Install NSIS 27 | shell: bash 28 | run: | 29 | sudo apt update 30 | sudo apt install -y nsis 31 | - name: Build Elixir Windows Installer 32 | shell: bash 33 | run: | 34 | export OTP_VERSION=${{ inputs.otp_version }} 35 | export ELIXIR_ZIP=$PWD/elixir-otp-${{ inputs.otp }}.zip 36 | (cd lib/elixir/scripts/windows_installer && ./build.sh) 37 | mv lib/elixir/scripts/windows_installer/tmp/elixir-otp-${{ inputs.otp }}.exe . 38 | - name: Get ExDoc ref 39 | if: ${{ inputs.build_docs }} 40 | shell: bash 41 | run: | 42 | if [ "${{ github.ref_name }}" = "main" ]; then 43 | ref=main 44 | else 45 | ref=v$(curl -s https://hex.pm/api/packages/ex_doc | jq --raw-output '.latest_stable_version') 46 | fi 47 | echo "EX_DOC_REF=$ref" >> $GITHUB_ENV 48 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 49 | if: ${{ inputs.build_docs }} 50 | with: 51 | repository: elixir-lang/ex_doc 52 | ref: ${{ env.EX_DOC_REF }} 53 | path: ex_doc 54 | - name: Build ex_doc 55 | if: ${{ inputs.build_docs }} 56 | shell: bash 57 | run: | 58 | mv ex_doc ../ex_doc 59 | cd ../ex_doc 60 | ../elixir/bin/mix do local.rebar --force + local.hex --force + deps.get + compile 61 | cd ../elixir 62 | - name: Build Docs 63 | if: ${{ inputs.build_docs }} 64 | shell: bash 65 | run: | 66 | git fetch --tags 67 | make Docs.zip 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | /doc/ 6 | /lib/*/ebin/ 7 | /lib/*/_build/ 8 | /lib/*/tmp/ 9 | /lib/elixir/src/*_parser.erl 10 | /lib/elixir/test/ebin/ 11 | /man/elixir.1 12 | /man/iex.1 13 | /Docs-v*.zip 14 | /Precompiled-v*.zip 15 | /.eunit 16 | .elixir.plt 17 | erl_crash.dump 18 | /cover/ 19 | -------------------------------------------------------------------------------- /.markdownlint.jsonc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | { 5 | // Consecutive header levels (h1 -> h2 -> h3). We don't care about this. 6 | "MD001": false, 7 | // Header style. We use #s. 8 | "MD003": { 9 | "style": "atx" 10 | }, 11 | // Style of unordered lists.. 12 | "MD007": { 13 | "indent": 2, 14 | "start_indented": true 15 | }, 16 | // Line length. Who cares. 17 | "MD013": false, 18 | // This warns if you have "console" or "shell" code blocks with a dollar sign $ that 19 | // don't show output. We use those a lot, so this is fine for us. 20 | "MD014": false, 21 | // Multiple headings with the same content. That's fine. 22 | "MD024": false, 23 | // Some headers finish with ! because it refers to a function name 24 | "MD026": false, 25 | // Allow empty line between block quotes. Used by contiguous admonition blocks. 26 | "MD028": false, 27 | // Allowed HTML inline elements. 28 | "MD033": { 29 | "allowed_elements": [ 30 | "h1", 31 | "a", 32 | "br", 33 | "img", 34 | "picture", 35 | "source", 36 | "noscript", 37 | "p", 38 | "script" 39 | ] 40 | }, 41 | // This warns if you have spaces in code blocks. Sometimes, that's fine. 42 | "MD038": false, 43 | // Code block style. We don't care if it's fenced or indented. 44 | "MD046": false 45 | } 46 | -------------------------------------------------------------------------------- /.ort/config/config.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | ort: 5 | enableRepositoryPackageCurations: true 6 | 7 | scanner: 8 | skipConcluded: false 9 | includeFilesWithoutFindings: true 10 | 11 | analyzer: 12 | allowDynamicVersions: true 13 | enabledPackageManagers: [SpdxDocumentFile] 14 | skipExcluded: true 15 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Release process 8 | 9 | ## Shipping a new version 10 | 11 | 1. Update version in /VERSION, bin/elixir, bin/elixir.bat, and bin/elixir.ps1 12 | 13 | 2. Ensure /CHANGELOG.md is updated, versioned and add the current date 14 | - If this release addresses any publicly known security vulnerabilities with 15 | assigned CVEs, add a "Security" section to `CHANGELOG.md`. For example: 16 | ```md 17 | ## Security 18 | - Fixed CVE-2025-00000: Description of the vulnerability 19 | ``` 20 | 21 | 3. Update "Compatibility and Deprecations" if a new OTP version is supported 22 | 23 | 4. Commit changes above with title "Release vVERSION" and push it 24 | 25 | 5. Once GitHub actions completes, generate a new tag, and push it 26 | 27 | 6. Wait until GitHub Actions publish artifacts to the draft release 28 | 29 | 7. Copy the relevant bits from /CHANGELOG.md to the GitHub release and publish it (link to the announcement if there is one) 30 | 31 | 8. Update `_data/elixir-versions.yml` (except for RCs) in `elixir-lang/elixir-lang.github.com` 32 | 33 | ## Creating a new vMAJOR.MINOR branch (before first rc) 34 | 35 | ### In the new branch 36 | 37 | 1. Comment the `CANONICAL=` in /Makefile 38 | 39 | 2. Update tables in /SECURITY.md and "Compatibility and Deprecations" 40 | 41 | 3. Commit "Branch out vMAJOR.MINOR" 42 | 43 | ### Back in main 44 | 45 | 1. Bump /VERSION file, bin/elixir, bin/elixir.bat, and bin/elixir.ps1 46 | 47 | 2. Start new /CHANGELOG.md 48 | 49 | 3. Update tables in /SECURITY.md and in "Compatibility and Deprecations" 50 | 51 | 4. Commit "Start vMAJOR.MINOR+1" 52 | 53 | ## Changing supported Erlang/OTP versions 54 | 55 | 1. Update the table in Compatibility and Deprecations 56 | 57 | 2. Update `otp_release` checks in `/Makefile` and `/lib/elixir/src/elixir.erl` 58 | 59 | 3. Update relevant CI workflows in `/.github/workflows/*.yml` - for release workflows, outdated/recently added Erlang/OTP versions must run conditionally 60 | 61 | 4. Remove `otp_release` version checks that are no longer needed 62 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Security Policy 8 | 9 | ## Supported versions 10 | 11 | Elixir applies bug fixes only to the latest minor branch. Security patches are available for the last 5 minor branches: 12 | 13 | Elixir version | Support 14 | :------------- | :----------------------------- 15 | 1.19 | Development 16 | 1.18 | Bug fixes and security patches 17 | 1.17 | Security patches only 18 | 1.16 | Security patches only 19 | 1.15 | Security patches only 20 | 1.14 | Security patches only 21 | 22 | ## Announcements 23 | 24 | New releases are announced in the read-only [announcements mailing list](https://groups.google.com/group/elixir-lang-ann). You can subscribe by sending an email to elixir-lang-ann+subscribe@googlegroups.com and replying to the confirmation email. Security notifications [will be tagged with `[security]`](https://groups.google.com/forum/#!searchin/elixir-lang-ann/%5Bsecurity%5D%7Csort:date). 25 | 26 | You may also see [all releases](https://github.com/elixir-lang/elixir/releases) and [consult all disclosed vulnerabilities](https://github.com/elixir-lang/elixir/security) on GitHub. 27 | 28 | ## Reporting a vulnerability 29 | 30 | [Please disclose security vulnerabilities privately via GitHub](https://github.com/elixir-lang/elixir/security). 31 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.19.0-dev 2 | -------------------------------------------------------------------------------- /bin/elixirc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # SPDX-License-Identifier: Apache-2.0 4 | # SPDX-FileCopyrightText: 2021 The Elixir Team 5 | # SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | set -e 8 | 9 | if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then 10 | cat <&2 11 | Usage: $(basename "$0") [elixir switches] [compiler switches] [.ex files] 12 | 13 | -h, --help Prints this message and exits 14 | -o The directory to output compiled files 15 | -v, --version Prints Elixir version and exits (standalone) 16 | 17 | --ignore-module-conflict Does not emit warnings if a module was previously defined 18 | --no-debug-info Does not attach debug info to compiled modules 19 | --no-docs Does not attach documentation to compiled modules 20 | --profile time Profile the time to compile modules 21 | --verbose Prints compilation status 22 | --warnings-as-errors Treats warnings as errors and return non-zero exit status 23 | 24 | Options given after -- are passed down to the executed code. 25 | Options can be passed to the Erlang runtime using \$ELIXIR_ERL_OPTIONS. 26 | Options can be passed to the Erlang compiler using \$ERL_COMPILER_OPTIONS. 27 | USAGE 28 | exit 1 29 | fi 30 | 31 | readlink_f () { 32 | cd "$(dirname "$1")" > /dev/null 33 | filename="$(basename "$1")" 34 | if [ -h "$filename" ]; then 35 | readlink_f "$(readlink "$filename")" 36 | else 37 | echo "$(pwd -P)/$filename" 38 | fi 39 | } 40 | 41 | SELF=$(readlink_f "$0") 42 | SCRIPT_PATH=$(dirname "$SELF") 43 | exec "$SCRIPT_PATH"/elixir +elixirc "$@" 44 | -------------------------------------------------------------------------------- /bin/elixirc.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: SPDX-License-Identifier: Apache-2.0 4 | :: SPDX-FileCopyrightText: 2021 The Elixir Team 5 | :: SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | setlocal 8 | set argc=0 9 | for %%A in (%*) do ( 10 | if /I "%%A"=="--help" goto documentation 11 | if /I "%%A"=="-h" goto documentation 12 | if /I "%%A"=="/h" goto documentation 13 | if "%%A"=="/?" goto documentation 14 | set /A argc+=1 15 | ) 16 | if %argc%==0 goto documentation 17 | goto run 18 | 19 | :documentation 20 | echo Usage: %~nx0 [elixir switches] [compiler switches] [.ex files] 21 | echo. 22 | echo -h, --help Prints this message and exits 23 | echo -o The directory to output compiled files 24 | echo -v, --version Prints Elixir version and exits (standalone) 25 | echo. 26 | echo --ignore-module-conflict Does not emit warnings if a module was previously defined 27 | echo --no-debug-info Does not attach debug info to compiled modules 28 | echo --no-docs Does not attach documentation to compiled modules 29 | echo --profile time Profile the time to compile modules 30 | echo --verbose Prints compilation status 31 | echo --warnings-as-errors Treats warnings as errors and returns non-zero exit status 32 | echo. 33 | echo ** Options given after -- are passed down to the executed code 34 | echo ** Options can be passed to the Erlang runtime using ELIXIR_ERL_OPTIONS 35 | echo ** Options can be passed to the Erlang compiler using ERL_COMPILER_OPTIONS 36 | goto end 37 | 38 | :run 39 | call "%~dp0\elixir.bat" +elixirc %* 40 | 41 | :end 42 | endlocal 43 | -------------------------------------------------------------------------------- /bin/iex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # SPDX-License-Identifier: Apache-2.0 4 | # SPDX-FileCopyrightText: 2021 The Elixir Team 5 | # SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | set -e 8 | 9 | if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then 10 | cat <&2 11 | Usage: $(basename "$0") [options] [.exs file] [data] 12 | 13 | The following options are exclusive to IEx: 14 | 15 | --dbg pry Sets the backend for Kernel.dbg/2 to IEx.pry/0 16 | --dot-iex "FILE" Evaluates FILE, line by line, to set up IEx' environment. 17 | Defaults to evaluating .iex.exs or ~/.iex.exs, if any exists. 18 | If FILE is empty, then no file will be loaded. 19 | --remsh NAME Connects to a node using a remote shell. 20 | 21 | It accepts all other options listed by "elixir --help". 22 | USAGE 23 | exit 1 24 | fi 25 | 26 | readlink_f () { 27 | cd "$(dirname "$1")" > /dev/null 28 | filename="$(basename "$1")" 29 | if [ -h "$filename" ]; then 30 | readlink_f "$(readlink "$filename")" 31 | else 32 | echo "$(pwd -P)/$filename" 33 | fi 34 | } 35 | 36 | SELF=$(readlink_f "$0") 37 | SCRIPT_PATH=$(dirname "$SELF") 38 | exec "$SCRIPT_PATH"/elixir --no-halt --erl "-user elixir" +iex "$@" 39 | -------------------------------------------------------------------------------- /bin/iex.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: SPDX-License-Identifier: Apache-2.0 4 | :: SPDX-FileCopyrightText: 2021 The Elixir Team 5 | :: SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | setlocal 8 | if /I ""%1""==""--help"" goto documentation 9 | if /I ""%1""==""-h"" goto documentation 10 | if /I ""%1""==""/h"" goto documentation 11 | if ""%1""==""/?"" goto documentation 12 | goto run 13 | 14 | :documentation 15 | echo Usage: %~nx0 [options] [.exs file] [data] 16 | echo. 17 | echo The following options are exclusive to IEx: 18 | echo. 19 | echo --dbg pry Sets the backend for Kernel.dbg/2 to IEx.pry/0 20 | echo --dot-iex "FILE" Evaluates FILE, line by line, to set up IEx' environment. 21 | echo Defaults to evaluating .iex.exs or ~/.iex.exs, if any exists. 22 | echo If FILE is empty, then no file will be loaded. 23 | echo --remsh NAME Connects to a node using a remote shell 24 | echo. 25 | echo It accepts all other options listed by "elixir --help". 26 | goto end 27 | 28 | :run 29 | call "%~dp0\elixir.bat" --no-halt --erl "-user elixir" +iex %* 30 | :end 31 | endlocal 32 | -------------------------------------------------------------------------------- /bin/mix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env elixir 2 | 3 | # SPDX-License-Identifier: Apache-2.0 4 | # SPDX-FileCopyrightText: 2021 The Elixir Team 5 | # SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | Mix.CLI.main() 8 | -------------------------------------------------------------------------------- /bin/mix.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: SPDX-License-Identifier: Apache-2.0 4 | :: SPDX-FileCopyrightText: 2021 The Elixir Team 5 | :: SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | call "%~dp0\elixir.bat" "%~dp0\mix" %* 8 | -------------------------------------------------------------------------------- /bin/mix.ps1: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | # Store path to mix.bat as a FileInfo object 6 | $mixBatPath = (Get-ChildItem (((Get-ChildItem $MyInvocation.MyCommand.Path).Directory.FullName) + '\mix.bat')) 7 | $newArgs = @() 8 | 9 | for ($i = 0; $i -lt $args.length; $i++) 10 | { 11 | if ($args[$i] -is [array]) 12 | { 13 | # Commas created the array so we need to reintroduce those commas 14 | for ($j = 0; $j -lt $args[$i].length - 1; $j++) 15 | { 16 | $newArgs += ($args[$i][$j] + ',') 17 | } 18 | $newArgs += $args[$i][-1] 19 | } 20 | else 21 | { 22 | $newArgs += $args[$i] 23 | } 24 | } 25 | 26 | # Corrected arguments are ready to pass to batch file 27 | & $mixBatPath $newArgs -------------------------------------------------------------------------------- /lib/eex/lib/eex/smart_engine.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule EEx.SmartEngine do 6 | @moduledoc """ 7 | The default engine used by EEx. 8 | 9 | It includes assigns (like `@foo`) and possibly other 10 | conveniences in the future. 11 | 12 | ## Examples 13 | 14 | iex> EEx.eval_string("<%= @foo %>", assigns: [foo: 1]) 15 | "1" 16 | 17 | In the example above, we can access the value `foo` under 18 | the binding `assigns` using `@foo`. This is useful because 19 | a template, after being compiled, can receive different 20 | assigns and would not require recompilation for each 21 | variable set. 22 | 23 | Assigns can also be used when compiled to a function: 24 | 25 | # sample.eex 26 | <%= @a + @b %> 27 | 28 | # sample.ex 29 | defmodule Sample do 30 | require EEx 31 | EEx.function_from_file(:def, :sample, "sample.eex", [:assigns]) 32 | end 33 | 34 | # iex 35 | Sample.sample(a: 1, b: 2) 36 | #=> "3" 37 | 38 | """ 39 | 40 | @behaviour EEx.Engine 41 | 42 | @impl true 43 | defdelegate init(opts), to: EEx.Engine 44 | 45 | @impl true 46 | defdelegate handle_body(state), to: EEx.Engine 47 | 48 | @impl true 49 | defdelegate handle_begin(state), to: EEx.Engine 50 | 51 | @impl true 52 | defdelegate handle_end(state), to: EEx.Engine 53 | 54 | @impl true 55 | defdelegate handle_text(state, meta, text), to: EEx.Engine 56 | 57 | @impl true 58 | def handle_expr(state, marker, expr) do 59 | expr = Macro.prewalk(expr, &EEx.Engine.handle_assign/1) 60 | EEx.Engine.handle_expr(state, marker, expr) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/eex/mix.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule EEx.MixProject do 6 | use Mix.Project 7 | 8 | def project do 9 | [ 10 | app: :eex, 11 | version: System.version(), 12 | build_per_environment: false 13 | ] 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/eex/test/eex/smart_engine_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule EEx.SmartEngineTest do 8 | use ExUnit.Case, async: true 9 | 10 | test "evaluates simple string" do 11 | assert_eval("foo bar", "foo bar") 12 | end 13 | 14 | test "evaluates with assigns as keywords" do 15 | assert_eval("1", "<%= @foo %>", assigns: [foo: 1]) 16 | end 17 | 18 | test "evaluates with assigns as a map" do 19 | assert_eval("1", "<%= @foo %>", assigns: %{foo: 1}) 20 | end 21 | 22 | test "error with missing assigns" do 23 | stderr = 24 | ExUnit.CaptureIO.capture_io(:stderr, fn -> 25 | assert_eval("", "<%= @foo %>", assigns: %{}) 26 | end) 27 | 28 | assert stderr =~ "assign @foo not available in EEx template" 29 | end 30 | 31 | test "evaluates with loops" do 32 | assert_eval("1\n2\n3\n", "<%= for x <- [1, 2, 3] do %><%= x %>\n<% end %>") 33 | end 34 | 35 | test "preserves line numbers in assignments" do 36 | result = EEx.compile_string("foo\n<%= @hello %>", engine: EEx.SmartEngine) 37 | 38 | Macro.prewalk(result, fn 39 | {_left, meta, [_, :hello]} -> 40 | assert Keyword.get(meta, :line) == 2 41 | send(self(), :found) 42 | 43 | node -> 44 | node 45 | end) 46 | 47 | assert_received :found 48 | end 49 | 50 | defp assert_eval(expected, actual, binding \\ []) do 51 | result = EEx.eval_string(actual, binding, file: __ENV__.file, engine: EEx.SmartEngine) 52 | assert result == expected 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/eex/test/fixtures/eex_template.eex: -------------------------------------------------------------------------------- 1 | foo <%= if true do %>bar.<% end %> 2 | -------------------------------------------------------------------------------- /lib/eex/test/fixtures/eex_template_with_bindings.eex: -------------------------------------------------------------------------------- 1 | foo <%= bar %> 2 | -------------------------------------------------------------------------------- /lib/eex/test/fixtures/eex_template_with_syntax_error.eex: -------------------------------------------------------------------------------- 1 | foo <%= bar 2 | -------------------------------------------------------------------------------- /lib/eex/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | {line_exclude, line_include} = 6 | if line = System.get_env("LINE"), do: {[:test], [line: line]}, else: {[], []} 7 | 8 | Code.require_file("../../elixir/scripts/cover_record.exs", __DIR__) 9 | CoverageRecorder.maybe_record("eex") 10 | 11 | ExUnit.start( 12 | trace: !!System.get_env("TRACE"), 13 | include: line_include, 14 | exclude: line_exclude 15 | ) 16 | -------------------------------------------------------------------------------- /lib/elixir/Emakefile: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | {'src/*', [ 6 | warn_unused_vars, 7 | warn_export_all, 8 | warn_shadow_vars, 9 | warn_unused_import, 10 | warn_unused_function, 11 | warn_bif_clash, 12 | warn_unused_record, 13 | warn_deprecated_function, 14 | warn_obsolete_guard, 15 | warn_exported_vars, 16 | %% Enable this when we require Erlang/OTP 27+ 17 | %% warnings_as_errors, 18 | debug_info, 19 | {outdir, "ebin/"} 20 | ]}. 21 | -------------------------------------------------------------------------------- /lib/elixir/lib/agent/server.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Agent.Server do 6 | @moduledoc false 7 | 8 | use GenServer 9 | 10 | def init(fun) do 11 | _ = initial_call(fun) 12 | {:ok, run(fun, [])} 13 | end 14 | 15 | def handle_call({:get, fun}, _from, state) do 16 | {:reply, run(fun, [state]), state} 17 | end 18 | 19 | def handle_call({:get_and_update, fun}, _from, state) do 20 | case run(fun, [state]) do 21 | {reply, state} -> {:reply, reply, state} 22 | other -> {:stop, {:bad_return_value, other}, state} 23 | end 24 | end 25 | 26 | def handle_call({:update, fun}, _from, state) do 27 | {:reply, :ok, run(fun, [state])} 28 | end 29 | 30 | def handle_cast({:cast, fun}, state) do 31 | {:noreply, run(fun, [state])} 32 | end 33 | 34 | def code_change(_old, state, fun) do 35 | {:ok, run(fun, [state])} 36 | end 37 | 38 | defp initial_call(mfa) do 39 | _ = Process.put(:"$initial_call", get_initial_call(mfa)) 40 | :ok 41 | end 42 | 43 | defp get_initial_call(fun) when is_function(fun, 0) do 44 | {:module, module} = Function.info(fun, :module) 45 | {:name, name} = Function.info(fun, :name) 46 | {module, name, 0} 47 | end 48 | 49 | defp get_initial_call({mod, fun, args}) do 50 | {mod, fun, length(args)} 51 | end 52 | 53 | defp run({m, f, a}, extra), do: apply(m, f, extra ++ a) 54 | defp run(fun, extra), do: apply(fun, extra) 55 | end 56 | -------------------------------------------------------------------------------- /lib/elixir/lib/atom.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Atom do 6 | @moduledoc """ 7 | Atoms are constants whose values are their own name. 8 | 9 | They are often useful to enumerate over distinct values, such as: 10 | 11 | iex> :apple 12 | :apple 13 | iex> :orange 14 | :orange 15 | iex> :watermelon 16 | :watermelon 17 | 18 | Atoms are equal if their names are equal. 19 | 20 | iex> :apple == :apple 21 | true 22 | iex> :apple == :orange 23 | false 24 | 25 | Often they are used to express the state of an operation, by using 26 | values such as `:ok` and `:error`. 27 | 28 | The booleans `true` and `false` are also atoms: 29 | 30 | iex> true == :true 31 | true 32 | iex> is_atom(false) 33 | true 34 | iex> is_boolean(:false) 35 | true 36 | 37 | Elixir allows you to skip the leading `:` for the atoms `false`, `true`, 38 | and `nil`. 39 | 40 | Atoms must be composed of Unicode characters such as letters, numbers, 41 | underscore, and `@`. If the keyword has a character that does not 42 | belong to the category above, such as spaces, you can wrap it in 43 | quotes: 44 | 45 | iex> :"this is an atom with spaces" 46 | :"this is an atom with spaces" 47 | 48 | """ 49 | 50 | @doc """ 51 | Converts an atom to a string. 52 | 53 | Inlined by the compiler. 54 | 55 | ## Examples 56 | 57 | iex> Atom.to_string(:foo) 58 | "foo" 59 | 60 | """ 61 | @spec to_string(atom) :: String.t() 62 | def to_string(atom) do 63 | :erlang.atom_to_binary(atom) 64 | end 65 | 66 | @doc """ 67 | Converts an atom to a charlist. 68 | 69 | Inlined by the compiler. 70 | 71 | ## Examples 72 | 73 | iex> Atom.to_charlist(:"An atom") 74 | ~c"An atom" 75 | 76 | """ 77 | @spec to_charlist(atom) :: charlist 78 | def to_charlist(atom) do 79 | :erlang.atom_to_list(atom) 80 | end 81 | 82 | @doc false 83 | @deprecated "Use Atom.to_charlist/1 instead" 84 | @spec to_char_list(atom) :: charlist 85 | def to_char_list(atom), do: Atom.to_charlist(atom) 86 | end 87 | -------------------------------------------------------------------------------- /lib/elixir/lib/inspect/error.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | defmodule Inspect.Error do 5 | @moduledoc """ 6 | Raised when a struct cannot be inspected. 7 | """ 8 | @enforce_keys [:exception_module, :exception_message, :stacktrace, :inspected_struct] 9 | defexception @enforce_keys 10 | 11 | @impl true 12 | def exception(arguments) when is_list(arguments) do 13 | exception = Keyword.fetch!(arguments, :exception) 14 | exception_module = exception.__struct__ 15 | exception_message = Exception.message(exception) |> String.trim_trailing("\n") 16 | stacktrace = Keyword.fetch!(arguments, :stacktrace) 17 | inspected_struct = Keyword.fetch!(arguments, :inspected_struct) 18 | 19 | %Inspect.Error{ 20 | exception_module: exception_module, 21 | exception_message: exception_message, 22 | stacktrace: stacktrace, 23 | inspected_struct: inspected_struct 24 | } 25 | end 26 | 27 | @impl true 28 | def message(%__MODULE__{ 29 | exception_module: exception_module, 30 | exception_message: exception_message, 31 | inspected_struct: inspected_struct 32 | }) do 33 | ~s''' 34 | got #{inspect(exception_module)} with message: 35 | 36 | """ 37 | #{pad(exception_message, 4)} 38 | """ 39 | 40 | while inspecting: 41 | 42 | #{pad(inspected_struct, 4)} 43 | ''' 44 | end 45 | 46 | @doc false 47 | def pad(message, padding_length) 48 | when is_binary(message) and is_integer(padding_length) and padding_length >= 0 do 49 | padding = String.duplicate(" ", padding_length) 50 | 51 | message 52 | |> String.split("\n") 53 | |> Enum.map(fn 54 | "" -> "\n" 55 | line -> [padding, line, ?\n] 56 | end) 57 | |> IO.iodata_to_binary() 58 | |> String.trim_trailing("\n") 59 | end 60 | end 61 | 62 | defimpl Inspect, for: Inspect.Error do 63 | @impl true 64 | def inspect(%{stacktrace: stacktrace} = inspect_error, _opts) do 65 | message = Exception.message(inspect_error) 66 | format_output(message, stacktrace) 67 | end 68 | 69 | defp format_output(message, [_ | _] = stacktrace) do 70 | stacktrace = Exception.format_stacktrace(stacktrace) 71 | 72 | """ 73 | #Inspect.Error< 74 | #{Inspect.Error.pad(message, 2)} 75 | 76 | Stacktrace: 77 | 78 | #{stacktrace} 79 | >\ 80 | """ 81 | end 82 | 83 | defp format_output(message, []) do 84 | """ 85 | #Inspect.Error< 86 | #{Inspect.Error.pad(message, 2)} 87 | >\ 88 | """ 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/elixir/lib/io/stream.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule IO.StreamError do 6 | defexception [:reason] 7 | 8 | @impl true 9 | def message(%{reason: reason}) do 10 | "error during streaming: #{inspect(reason)}" 11 | end 12 | end 13 | 14 | defmodule IO.Stream do 15 | @moduledoc """ 16 | Defines an `IO.Stream` struct returned by `IO.stream/2` and `IO.binstream/2`. 17 | 18 | The following fields are public: 19 | 20 | * `device` - the IO device 21 | * `raw` - a boolean indicating if bin functions should be used 22 | * `line_or_bytes` - if reading should read lines or a given number of bytes 23 | 24 | It is worth noting that an IO stream has side effects and every time you go 25 | over the stream you may get different results. 26 | 27 | """ 28 | 29 | defstruct device: nil, raw: true, line_or_bytes: :line 30 | 31 | @type t :: %__MODULE__{ 32 | device: IO.device(), 33 | raw: boolean(), 34 | line_or_bytes: :line | non_neg_integer() 35 | } 36 | 37 | @doc false 38 | def __build__(device, raw, line_or_bytes) do 39 | %IO.Stream{device: device, raw: raw, line_or_bytes: line_or_bytes} 40 | end 41 | 42 | defimpl Collectable do 43 | def into(%{device: device, raw: raw} = stream) do 44 | {:ok, into(stream, device, raw)} 45 | end 46 | 47 | defp into(stream, device, raw) do 48 | fn 49 | :ok, {:cont, x} -> 50 | case raw do 51 | true -> IO.binwrite(device, x) 52 | false -> IO.write(device, x) 53 | end 54 | 55 | :ok, _ -> 56 | stream 57 | end 58 | end 59 | end 60 | 61 | defimpl Enumerable do 62 | def reduce(%{device: device, raw: raw, line_or_bytes: line_or_bytes}, acc, fun) do 63 | next_fun = 64 | case raw do 65 | true -> &IO.each_binstream(&1, line_or_bytes) 66 | false -> &IO.each_stream(&1, line_or_bytes) 67 | end 68 | 69 | Stream.resource(fn -> device end, next_fun, & &1).(acc, fun) 70 | end 71 | 72 | def count(_stream) do 73 | {:error, __MODULE__} 74 | end 75 | 76 | def member?(_stream, _term) do 77 | {:error, __MODULE__} 78 | end 79 | 80 | def slice(_stream) do 81 | {:error, __MODULE__} 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/elixir/lib/kernel/error_handler.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | # Implement error_handler pattern for Erlang 6 | # which is integrated with Kernel.ParallelCompiler 7 | defmodule Kernel.ErrorHandler do 8 | @moduledoc false 9 | 10 | @spec undefined_function(module, atom, list) :: term 11 | def undefined_function(module, fun, args) do 12 | ensure_loaded(module) or ensure_compiled(module, :module, :raise, nil) 13 | :error_handler.undefined_function(module, fun, args) 14 | end 15 | 16 | @spec undefined_lambda(module, fun, list) :: term 17 | def undefined_lambda(module, fun, args) do 18 | ensure_loaded(module) or ensure_compiled(module, :module, :raise, nil) 19 | :error_handler.undefined_lambda(module, fun, args) 20 | end 21 | 22 | @spec ensure_loaded(module) :: boolean 23 | def ensure_loaded(module) do 24 | case :code.ensure_loaded(module) do 25 | {:module, _} -> true 26 | {:error, _} -> false 27 | end 28 | end 29 | 30 | @spec ensure_compiled(module, atom, atom, nil | integer()) :: :found | :not_found | :deadlock 31 | # Never wait on nil because it should never be defined. 32 | def ensure_compiled(nil, _kind, _deadlock, _position) do 33 | :not_found 34 | end 35 | 36 | def ensure_compiled(module, kind, deadlock, position) do 37 | {compiler_pid, file_pid} = :erlang.get(:elixir_compiler_info) 38 | ref = :erlang.make_ref() 39 | modules = :elixir_module.compiler_modules() 40 | 41 | send( 42 | compiler_pid, 43 | {:waiting, kind, self(), ref, file_pid, position, module, modules, deadlock} 44 | ) 45 | 46 | :erlang.garbage_collect(self()) 47 | 48 | receive do 49 | {^ref, {:loading, pid}} -> 50 | ref = :erlang.monitor(:process, pid) 51 | 52 | receive do 53 | {:DOWN, ^ref, _, _, _} -> :found 54 | end 55 | 56 | {^ref, value} -> 57 | value 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/elixir/lib/kernel/parallel_require.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Kernel.ParallelRequire do 6 | @moduledoc false 7 | @moduledoc deprecated: "Use the Kernel.ParallelCompiler module instead" 8 | 9 | @deprecated "Use Kernel.ParallelCompiler.require/2 instead" 10 | def files(files, callbacks \\ []) 11 | 12 | def files(files, callback) when is_function(callback, 1) do 13 | files(files, each_file: callback) 14 | end 15 | 16 | def files(files, options) when is_list(options) do 17 | case Kernel.ParallelCompiler.require(files, options) do 18 | {:ok, modules, _} -> modules 19 | {:error, _, _} -> exit({:shutdown, 1}) 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/elixir/lib/list/chars.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defprotocol List.Chars do 6 | @moduledoc ~S""" 7 | The `List.Chars` protocol is responsible for 8 | converting a structure to a charlist (only if applicable). 9 | 10 | The only function that must be implemented is 11 | `to_charlist/1` which does the conversion. 12 | 13 | The `to_charlist/1` function automatically imported 14 | by `Kernel` invokes this protocol. 15 | """ 16 | 17 | @doc """ 18 | Converts `term` to a charlist. 19 | """ 20 | @spec to_charlist(t) :: charlist 21 | def to_charlist(term) 22 | 23 | @doc false 24 | @deprecated "Use List.Chars.to_charlist/1 instead" 25 | Kernel.def to_char_list(term) do 26 | __MODULE__.to_charlist(term) 27 | end 28 | end 29 | 30 | defimpl List.Chars, for: Atom do 31 | def to_charlist(nil), do: ~c"" 32 | 33 | def to_charlist(atom), do: Atom.to_charlist(atom) 34 | end 35 | 36 | defimpl List.Chars, for: BitString do 37 | @doc """ 38 | Returns the given binary `term` converted to a charlist. 39 | """ 40 | def to_charlist(term) when is_binary(term) do 41 | String.to_charlist(term) 42 | end 43 | 44 | def to_charlist(term) do 45 | raise Protocol.UndefinedError, 46 | protocol: @protocol, 47 | value: term, 48 | description: "cannot convert a bitstring to a charlist" 49 | end 50 | end 51 | 52 | defimpl List.Chars, for: List do 53 | # Note that same inlining is used for the rewrite rule. 54 | def to_charlist(list), do: list 55 | end 56 | 57 | defimpl List.Chars, for: Integer do 58 | def to_charlist(term) do 59 | Integer.to_charlist(term) 60 | end 61 | end 62 | 63 | defimpl List.Chars, for: Float do 64 | def to_charlist(term) do 65 | Float.to_charlist(term) 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/elixir/lib/string/chars.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | import Kernel, except: [to_string: 1] 6 | 7 | defprotocol String.Chars do 8 | @moduledoc ~S""" 9 | The `String.Chars` protocol is responsible for 10 | converting a structure to a binary (only if applicable). 11 | 12 | The only function required to be implemented is 13 | `to_string/1`, which does the conversion. 14 | 15 | The `to_string/1` function automatically imported 16 | by `Kernel` invokes this protocol. String 17 | interpolation also invokes `to_string/1` in its 18 | arguments. For example, `"foo#{bar}"` is the same 19 | as `"foo" <> to_string(bar)`. 20 | """ 21 | 22 | @doc """ 23 | Converts `term` to a string. 24 | """ 25 | @spec to_string(t) :: String.t() 26 | def to_string(term) 27 | end 28 | 29 | defimpl String.Chars, for: Atom do 30 | def to_string(nil) do 31 | "" 32 | end 33 | 34 | def to_string(atom) do 35 | Atom.to_string(atom) 36 | end 37 | end 38 | 39 | defimpl String.Chars, for: BitString do 40 | def to_string(term) when is_binary(term) do 41 | term 42 | end 43 | 44 | def to_string(term) do 45 | raise Protocol.UndefinedError, 46 | protocol: @protocol, 47 | value: term, 48 | description: "cannot convert a bitstring to a string" 49 | end 50 | end 51 | 52 | defimpl String.Chars, for: List do 53 | def to_string(charlist), do: List.to_string(charlist) 54 | end 55 | 56 | defimpl String.Chars, for: Integer do 57 | def to_string(term) do 58 | Integer.to_string(term) 59 | end 60 | end 61 | 62 | defimpl String.Chars, for: Float do 63 | def to_string(term) do 64 | Float.to_string(term) 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/elixir/lib/supervisor/default.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Supervisor.Default do 6 | @moduledoc false 7 | 8 | def init(args) do 9 | args 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/elixir/mix.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Elixir.MixProject do 6 | use Mix.Project 7 | 8 | def project do 9 | [ 10 | app: :elixir, 11 | version: System.version(), 12 | build_per_environment: false 13 | ] 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/elixir/pages/images/kv-observer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/pages/images/kv-observer.png -------------------------------------------------------------------------------- /lib/elixir/pages/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/pages/images/logo.png -------------------------------------------------------------------------------- /lib/elixir/scripts/cover.exs: -------------------------------------------------------------------------------- 1 | #!bin/elixir 2 | 3 | # SPDX-License-Identifier: Apache-2.0 4 | # SPDX-FileCopyrightText: 2021 The Elixir Team 5 | 6 | Code.require_file("cover_record.exs", __DIR__) 7 | cover_pid = CoverageRecorder.enable_coverage() 8 | 9 | coverdata_inputs = 10 | CoverageRecorder.cover_dir() |> Path.join("ex_unit_*.coverdata") |> Path.wildcard() 11 | 12 | coverdata_output = Path.join(CoverageRecorder.cover_dir(), "combined.coverdata") 13 | 14 | for file <- coverdata_inputs do 15 | :ok = :cover.import(String.to_charlist(file)) 16 | end 17 | 18 | :ok = :cover.export(String.to_charlist(coverdata_output)) 19 | 20 | {:ok, _} = Application.ensure_all_started(:mix) 21 | 22 | # Silence analyse import messages emitted by cover 23 | {:ok, string_io} = StringIO.open("") 24 | Process.group_leader(cover_pid, string_io) 25 | 26 | :ok = 27 | Mix.Tasks.Test.Coverage.generate_cover_results( 28 | output: CoverageRecorder.cover_dir(), 29 | summary: [threshold: 0] 30 | ) 31 | -------------------------------------------------------------------------------- /lib/elixir/scripts/cover_record.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | defmodule CoverageRecorder do 5 | def maybe_record(suite_name) do 6 | if enabled?() do 7 | record(suite_name) 8 | 9 | true 10 | else 11 | false 12 | end 13 | end 14 | 15 | def enable_coverage do 16 | _ = :cover.stop() 17 | {:ok, pid} = :cover.start() 18 | 19 | cover_compile_ebins() 20 | 21 | pid 22 | end 23 | 24 | def cover_dir, do: Path.join(root_dir(), "cover") 25 | 26 | defp enabled? do 27 | case System.fetch_env("COVER") do 28 | {:ok, truthy} when truthy in ~w[1 true yes y] -> 29 | true 30 | 31 | _ -> 32 | false 33 | end 34 | end 35 | 36 | defp root_dir, do: Path.join(__DIR__, "../../..") 37 | defp ebins, do: root_dir() |> Path.join("lib/*/ebin") |> Path.wildcard() 38 | 39 | defp record(suite_name) do 40 | file = Path.join(cover_dir(), "ex_unit_#{suite_name}.coverdata") 41 | 42 | enable_coverage() 43 | 44 | System.at_exit(fn _status -> 45 | File.mkdir_p!(cover_dir()) 46 | 47 | :ok = :cover.export(String.to_charlist(file)) 48 | end) 49 | end 50 | 51 | defp cover_compile_ebins do 52 | relevant_beam_files() 53 | |> Enum.map(&String.to_charlist/1) 54 | |> :cover.compile_beam() 55 | |> Enum.each(fn 56 | {:ok, _module} -> 57 | :ok 58 | 59 | {:error, reason} -> 60 | raise "Failed to cover compile with reason: #{inspect(reason)}" 61 | end) 62 | end 63 | 64 | defp relevant_beam_files do 65 | ebins() 66 | |> Enum.flat_map(fn ebin -> 67 | ebin |> Path.join("*.beam") |> Path.wildcard() 68 | end) 69 | |> Enum.reject(&skip_from_coverage?/1) 70 | end 71 | 72 | @to_skip [ 73 | # Tested via the CLI only 74 | :elixir_sup, 75 | :iex, 76 | Kernel.CLI, 77 | Mix.CLI, 78 | Mix.Compilers.Test, 79 | Mix.Tasks.Test, 80 | Mix.Tasks.Test.Coverage, 81 | 82 | # Bootstrap 83 | :elixir_bootstrap, 84 | Kernel.SpecialForms 85 | ] 86 | 87 | defp skip_from_coverage?(file) do 88 | mod = file |> Path.basename(".beam") |> String.to_atom() 89 | mod in @to_skip or match?({:docs_v1, _, _, _, _, %{deprecated: _}, _}, Code.fetch_docs(mod)) 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /lib/elixir/scripts/docs_config.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | # Generate docs_config.js for version chooser in ExDoc 5 | [app] = System.argv() 6 | 7 | {text_tags, 0} = System.cmd("git", ["tag"]) 8 | skipped = Version.parse!("1.0.3") 9 | 10 | versions = 11 | for( 12 | "v" <> rest <- String.split(text_tags), 13 | not String.ends_with?(rest, "-latest"), 14 | version = Version.parse!(rest), 15 | Version.compare(version, skipped) == :gt, 16 | do: version 17 | ) 18 | |> Enum.sort({:desc, Version}) 19 | 20 | latest = 21 | versions 22 | |> Stream.filter(&(&1.pre == [])) 23 | |> Enum.fetch!(0) 24 | |> Version.to_string() 25 | 26 | version_nodes = 27 | for version <- versions do 28 | version_string = Version.to_string(version) 29 | map = %{version: "v#{version_string}", url: "https://hexdocs.pm/#{app}/#{version_string}"} 30 | 31 | if version_string == latest do 32 | Map.put(map, :latest, true) 33 | else 34 | map 35 | end 36 | end 37 | 38 | search_nodes = 39 | for app <- ~w(eex elixir ex_unit iex logger mix)s do 40 | %{name: app, version: latest} 41 | end 42 | 43 | File.mkdir_p!("doc/#{app}") 44 | 45 | File.write!("doc/#{app}/docs_config.js", """ 46 | var versionNodes = #{JSON.encode_to_iodata!(version_nodes)}; 47 | var searchNodes = #{JSON.encode_to_iodata!(search_nodes)}; 48 | """) 49 | -------------------------------------------------------------------------------- /lib/elixir/scripts/generate_app.escript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env escript 2 | 3 | %% SPDX-License-Identifier: Apache-2.0 4 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 5 | %% SPDX-FileCopyrightText: 2012 Plataformatec 6 | 7 | %% -*- erlang -*- 8 | 9 | main([Version]) -> 10 | Source = "lib/elixir/src/elixir.app.src", 11 | Target = "lib/elixir/ebin/elixir.app", 12 | {ok, [{application, Name, Props0}]} = file:consult(Source), 13 | Ebin = filename:dirname(Target), 14 | Files = filelib:wildcard(filename:join(Ebin, "*.beam")), 15 | Mods = [list_to_atom(filename:basename(F, ".beam")) || F <- Files], 16 | Props1 = lists:keyreplace(modules, 1, Props0, {modules, Mods}), 17 | Props = lists:keyreplace(vsn, 1, Props1, {vsn, Version}), 18 | AppDef = io_lib:format("~tp.~n", [{application, Name, Props}]), 19 | ok = file:write_file(Target, AppDef), 20 | io:format("Generated ~ts app~n", [Name]). 21 | -------------------------------------------------------------------------------- /lib/elixir/scripts/mix_docs.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | # Returns config for other apps except Elixir 5 | canonical = System.fetch_env!("CANONICAL") 6 | 7 | [ 8 | deps: [ 9 | eex: "https://hexdocs.pm/eex/#{canonical}", 10 | elixir: "https://hexdocs.pm/elixir/#{canonical}", 11 | ex_unit: "https://hexdocs.pm/ex_unit/#{canonical}", 12 | iex: "https://hexdocs.pm/iex/#{canonical}", 13 | logger: "https://hexdocs.pm/logger/#{canonical}", 14 | mix: "https://hexdocs.pm/mix/#{canonical}" 15 | ], 16 | formatters: ["html", "epub"], 17 | before_closing_body_tag: fn 18 | :html -> 19 | """ 20 | 21 | 48 | """ 49 | 50 | _ -> 51 | "" 52 | end 53 | ] 54 | -------------------------------------------------------------------------------- /lib/elixir/scripts/windows_installer/.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | tmp/ 6 | -------------------------------------------------------------------------------- /lib/elixir/scripts/windows_installer/assets/Elixir.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/scripts/windows_installer/assets/Elixir.ico -------------------------------------------------------------------------------- /lib/elixir/scripts/windows_installer/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-License-Identifier: Apache-2.0 4 | # SPDX-FileCopyrightText: 2021 The Elixir Team 5 | 6 | # Usage: 7 | # 8 | # With Elixir archive: 9 | # 10 | # ELIXIR_ZIP=Precompiled.zip OTP_VERSION=25.3.2.2 ./build.sh 11 | set -euo pipefail 12 | 13 | mkdir -p tmp 14 | rm -rf tmp/elixir 15 | unzip -d "tmp/elixir" "${ELIXIR_ZIP}" 16 | 17 | elixir_version=`cat tmp/elixir/VERSION` 18 | otp_release=`erl -noshell -eval 'io:put_chars(erlang:system_info(otp_release)), halt().'` 19 | otp_version=`erl -noshell -eval '{ok, Vsn} = file:read_file(code:root_dir() ++ "/releases/" ++ erlang:system_info(otp_release) ++ "/OTP_VERSION"), io:put_chars(Vsn), halt().'` 20 | elixir_exe=elixir-otp-${otp_release}.exe 21 | 22 | # brew install makensis 23 | # apt install -y nsis 24 | # choco install -y nsis 25 | export PATH="/c/Program Files (x86)/NSIS:${PATH}" 26 | makensis \ 27 | -X"OutFile tmp\\${elixir_exe}" \ 28 | -DOTP_RELEASE="${otp_release}" \ 29 | -DOTP_VERSION=${otp_version} \ 30 | -DELIXIR_DIR=tmp\\elixir \ 31 | -DELIXIR_VERSION=${elixir_version} \ 32 | installer.nsi 33 | 34 | echo "Installer path: tmp/${elixir_exe}" 35 | -------------------------------------------------------------------------------- /lib/elixir/scripts/windows_installer/update_system_path.erl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env escript 2 | %% SPDX-License-Identifier: Apache-2.0 3 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 4 | 5 | %%! -noinput 6 | 7 | %% This file is used by the Elixir installer and uninstaller. 8 | main(["add", ";" ++ PathsToAdd]) -> 9 | {ok, Reg} = win32reg:open([read, write]), 10 | ok = win32reg:change_key(Reg, "\\hkey_current_user\\environment"), 11 | {ok, SystemPath} = win32reg:value(Reg, "path"), 12 | 13 | NewSystemPath = 14 | lists:foldl( 15 | fun(Elem, Acc) -> 16 | Elem ++ ";" ++ 17 | binary_to_list( 18 | iolist_to_binary( 19 | string:replace(Acc, Elem ++ ";", "", all))) 20 | end, 21 | SystemPath, 22 | string:split(PathsToAdd, ";", all) 23 | ), 24 | 25 | ok = win32reg:set_value(Reg, "Path", NewSystemPath), 26 | ok; 27 | 28 | main(["remove", ";" ++ PathsToRemove]) -> 29 | {ok, Reg} = win32reg:open([read, write]), 30 | ok = win32reg:change_key(Reg, "\\hkey_current_user\\environment"), 31 | {ok, SystemPath} = win32reg:value(Reg, "path"), 32 | 33 | NewSystemPath = 34 | lists:foldl( 35 | fun(Elem, Acc) -> 36 | binary_to_list( 37 | iolist_to_binary( 38 | string:replace(Acc, Elem ++ ";", "", all))) 39 | end, 40 | SystemPath, 41 | string:split(PathsToRemove, ";", all) 42 | ), 43 | 44 | ok = win32reg:set_value(Reg, "Path", NewSystemPath), 45 | ok. 46 | -------------------------------------------------------------------------------- /lib/elixir/src/elixir.app.src: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | {application, elixir, 6 | [{description, "elixir"}, 7 | {vsn, '$will-be-replaced'}, 8 | {modules, '$will-be-replaced'}, 9 | {registered, [elixir_sup, elixir_config, elixir_code_server]}, 10 | {applications, [kernel,stdlib,compiler]}, 11 | {mod, {elixir,[]}}, 12 | {env, [ 13 | {ansi_syntax_colors, [ 14 | {atom, cyan}, 15 | {binary, default_color}, 16 | {boolean, magenta}, 17 | {charlist, yellow}, 18 | {list, default_color}, 19 | {map, default_color}, 20 | {nil, magenta}, 21 | {number, yellow}, 22 | {string, green}, 23 | {tuple, default_color}, 24 | {variable, light_cyan}, 25 | {call, default_color}, 26 | {operator, default_color} 27 | ]}, 28 | {check_endianness, true}, 29 | {dbg_callback, {'Elixir.Macro', dbg, []}}, 30 | {time_zone_database, 'Elixir.Calendar.UTCOnlyTimeZoneDatabase'} 31 | ]} 32 | ]}. 33 | -------------------------------------------------------------------------------- /lib/elixir/src/elixir_bootstrap.erl: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | %% An Erlang module that behaves like an Elixir module 6 | %% used for bootstrapping. 7 | -module(elixir_bootstrap). 8 | -export(['MACRO-def'/2, 'MACRO-def'/3, 'MACRO-defp'/3, 'MACRO-defmodule'/3, 9 | 'MACRO-defmacro'/2, 'MACRO-defmacro'/3, 'MACRO-defmacrop'/3, 10 | 'MACRO-@'/2, '__info__'/1]). 11 | -define(kernel, 'Elixir.Kernel'). 12 | 13 | %% Mock out @ to be a no-op unless Kernel is defined. 14 | 'MACRO-@'(Caller, Tree) -> 15 | unless_loaded('MACRO-@', [Caller, Tree], fun() -> nil end). 16 | 17 | 'MACRO-def'(Caller, Call) -> 'MACRO-def'(Caller, Call, nil). 18 | 'MACRO-def'(Caller, Call, Expr) -> define(Caller, def, Call, Expr). 19 | 'MACRO-defp'(Caller, Call, Expr) -> define(Caller, defp, Call, Expr). 20 | 21 | 'MACRO-defmacro'(Caller, Call) -> 'MACRO-defmacro'(Caller, Call, nil). 22 | 'MACRO-defmacro'(Caller, Call, Expr) -> define(Caller, defmacro, Call, Expr). 23 | 'MACRO-defmacrop'(Caller, Call, Expr) -> define(Caller, defmacrop, Call, Expr). 24 | 25 | 'MACRO-defmodule'({Line, _S, _E} = _Caller, Alias, [{do, Block}]) -> 26 | Escaped = elixir_quote:escape(Block, none, false), 27 | Args = [[{line, Line}], Alias, Escaped, [], false, env()], 28 | {{'.', [], [elixir_module, compile]}, [], Args}. 29 | 30 | '__info__'(functions) -> 31 | []; 32 | '__info__'(macros) -> 33 | [{'@', 1}, 34 | {def, 1}, 35 | {def, 2}, 36 | {defmacro, 1}, 37 | {defmacro, 2}, 38 | {defmacrop, 2}, 39 | {defmodule, 2}, 40 | {defp, 2}]. 41 | 42 | define({Line, _S, #{module := Module} = E}, Kind, Call, Expr) -> 43 | UC = elixir_quote:has_unquotes(Call), 44 | UE = elixir_quote:has_unquotes(Expr), 45 | 46 | Store = 47 | case UC or UE of 48 | true -> 49 | elixir_quote:escape({Call, Expr}, none, true); 50 | 51 | false -> 52 | Key = erlang:unique_integer(), 53 | elixir_module:write_cache(Module, Key, {Call, Expr}), 54 | Key 55 | end, 56 | 57 | Args = [Kind, Store, elixir_module:cache_env(E#{line := Line})], 58 | {{'.', [], [elixir_def, store_definition]}, [], Args}. 59 | 60 | unless_loaded(Fun, Args, Callback) -> 61 | case erlang:module_loaded(?kernel) of 62 | true -> apply(?kernel, Fun, Args); 63 | false -> Callback() 64 | end. 65 | 66 | env() -> 67 | {'__ENV__', [], nil}. 68 | -------------------------------------------------------------------------------- /lib/elixir/src/elixir_erl_clauses.erl: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | %% Handle code related to args, guard and -> matching for case, 6 | %% fn, receive and friends. try is handled in elixir_erl_try. 7 | -module(elixir_erl_clauses). 8 | -export([match/4, clause/6, clauses/2, guards/4, get_clauses/3]). 9 | -include("elixir.hrl"). 10 | 11 | %% Get clauses under the given key. 12 | 13 | get_clauses(Key, Keyword, As) -> 14 | case lists:keyfind(Key, 1, Keyword) of 15 | {Key, Clauses} when is_list(Clauses) -> 16 | [{As, Meta, Left, Right} || {'->', Meta, [Left, Right]} <- Clauses]; 17 | _ -> 18 | [] 19 | end. 20 | 21 | %% Translate matches 22 | 23 | match(Ann, Fun, Match, #elixir_erl{context=Context} = S) when Context =/= match -> 24 | {Result, NewS} = Fun(Match, Ann, S#elixir_erl{context=match}), 25 | {Result, NewS#elixir_erl{context=Context}}; 26 | match(Ann, Fun, Match, S) -> 27 | Fun(Match, Ann, S). 28 | 29 | %% Translate clauses with args, guards and expressions 30 | 31 | clause(Ann, Fun, Match, Expr, Guards, S) -> 32 | {TMatch, SA} = match(Ann, Fun, Match, S), 33 | SG = SA#elixir_erl{extra_guards=[]}, 34 | TGuards = guards(Ann, Guards, SA#elixir_erl.extra_guards, SG), 35 | {TExpr, SE} = elixir_erl_pass:translate(Expr, Ann, SG), 36 | {{clause, Ann, TMatch, TGuards, unblock(TExpr)}, SE}. 37 | 38 | % Translate/Extract guards from the given expression. 39 | 40 | guards(Ann, Guards, Extra, S) -> 41 | SG = S#elixir_erl{context=guard}, 42 | case Guards of 43 | [] -> case Extra of [] -> []; _ -> [Extra] end; 44 | _ -> [translate_guard(Guard, Ann, SG, Extra) || Guard <- Guards] 45 | end. 46 | 47 | translate_guard(Guard, Ann, S, Extra) -> 48 | [element(1, elixir_erl_pass:translate(Guard, Ann, S)) | Extra]. 49 | 50 | % Function for translating macros with match style like case and receive. 51 | 52 | clauses([], S) -> 53 | {[], S}; 54 | 55 | clauses(Clauses, S) -> 56 | lists:mapfoldl(fun each_clause/2, S, Clauses). 57 | 58 | each_clause({match, Meta, [Condition], Expr}, S) -> 59 | {Arg, Guards} = elixir_utils:extract_guards(Condition), 60 | clause(?ann(Meta), fun elixir_erl_pass:translate_args/3, [Arg], Expr, Guards, S); 61 | 62 | each_clause({expr, Meta, [Condition], Expr}, S) -> 63 | Ann = ?ann(Meta), 64 | {TCondition, SC} = elixir_erl_pass:translate(Condition, Ann, S), 65 | {TExpr, SB} = elixir_erl_pass:translate(Expr, Ann, SC), 66 | {{clause, Ann, [TCondition], [], unblock(TExpr)}, SB}. 67 | 68 | unblock({'block', _, Exprs}) -> Exprs; 69 | unblock(Exprs) -> [Exprs]. 70 | -------------------------------------------------------------------------------- /lib/elixir/src/elixir_sup.erl: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | -module(elixir_sup). 6 | -behaviour(supervisor). 7 | -export([init/1, start_link/0]). 8 | 9 | start_link() -> 10 | supervisor:start_link({local, ?MODULE}, ?MODULE, ok). 11 | 12 | init(ok) -> 13 | Workers = [ 14 | { 15 | elixir_config, 16 | {elixir_config, start_link, []}, 17 | 18 | permanent, % Restart = permanent | transient | temporary 19 | 2000, % Shutdown = brutal_kill | int() >= 0 | infinity 20 | worker, % Type = worker | supervisor 21 | [elixir_config] % Modules = [Module] | dynamic 22 | }, 23 | 24 | { 25 | elixir_code_server, 26 | {elixir_code_server, start_link, []}, 27 | 28 | permanent, % Restart = permanent | transient | temporary 29 | 2000, % Shutdown = brutal_kill | int() >= 0 | infinity 30 | worker, % Type = worker | supervisor 31 | [elixir_code_server] % Modules = [Module] | dynamic 32 | } 33 | ], 34 | 35 | {ok, {{one_for_one, 3, 10}, Workers}}. 36 | -------------------------------------------------------------------------------- /lib/elixir/src/elixir_tokenizer.hrl: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | %% Numbers 5 | -define(is_hex(S), (?is_digit(S) orelse (S >= $A andalso S =< $F) orelse (S >= $a andalso S =< $f))). 6 | -define(is_bin(S), (S >= $0 andalso S =< $1)). 7 | -define(is_octal(S), (S >= $0 andalso S =< $7)). 8 | 9 | %% Digits and letters 10 | -define(is_digit(S), (S >= $0 andalso S =< $9)). 11 | -define(is_upcase(S), (S >= $A andalso S =< $Z)). 12 | -define(is_downcase(S), (S >= $a andalso S =< $z)). 13 | 14 | %% Others 15 | -define(is_quote(S), (S =:= $" orelse S =:= $')). 16 | -define(is_sigil(S), (S =:= $/ orelse S =:= $< orelse S =:= $" orelse S =:= $' orelse 17 | S =:= $[ orelse S =:= $( orelse S =:= ${ orelse S =:= $|)). 18 | -define(LOC(Line, Column), [{line, Line}, {column, Column}]). 19 | 20 | %% Spaces 21 | -define(is_horizontal_space(S), (S =:= $\s orelse S =:= $\t)). 22 | -define(is_vertical_space(S), (S =:= $\r orelse S =:= $\n)). 23 | -define(is_space(S), (?is_horizontal_space(S) orelse ?is_vertical_space(S))). 24 | 25 | %% Bidirectional control 26 | %% Retrieved from https://trojansource.codes/trojan-source.pdf 27 | -define(bidi(C), C =:= 16#202A; 28 | C =:= 16#202B; 29 | C =:= 16#202D; 30 | C =:= 16#202E; 31 | C =:= 16#2066; 32 | C =:= 16#2067; 33 | C =:= 16#2068; 34 | C =:= 16#202C; 35 | C =:= 16#2069). 36 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/atom_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule AtomTest do 8 | use ExUnit.Case, async: true 9 | 10 | doctest Atom, except: [:moduledoc] 11 | 12 | test "to_string/1" do 13 | assert "héllo" |> String.to_atom() |> Atom.to_string() == "héllo" 14 | end 15 | 16 | test "to_charlist/1" do 17 | assert "héllo" |> String.to_atom() |> Atom.to_charlist() == ~c"héllo" 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/bitwise_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule BitwiseTest do 8 | use ExUnit.Case, async: true 9 | 10 | import Bitwise 11 | doctest Bitwise 12 | 13 | test "bnot/1" do 14 | assert bnot(1) == -2 15 | end 16 | 17 | test "band/2" do 18 | assert band(1, 1) == 1 19 | end 20 | 21 | test "bor/2" do 22 | assert bor(0, 1) == 1 23 | end 24 | 25 | test "bxor/2" do 26 | assert bxor(1, 1) == 0 27 | end 28 | 29 | test "bsl/2" do 30 | assert bsl(1, 1) == 2 31 | end 32 | 33 | test "bsr/2" do 34 | assert bsr(1, 1) == 0 35 | end 36 | 37 | test "band (&&&)" do 38 | assert (1 &&& 1) == 1 39 | end 40 | 41 | test "bor (|||)" do 42 | assert (0 ||| 1) == 1 43 | end 44 | 45 | test "bsl (<<<)" do 46 | assert 1 <<< 1 == 2 47 | end 48 | 49 | test "bsr (>>>)" do 50 | assert 1 >>> 1 == 0 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/changelog_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | ExUnit.start() 5 | 6 | defmodule ChangelogTest do 7 | use ExUnit.Case, async: true 8 | doctest_file(Path.expand("../../../../CHANGELOG.md", __DIR__)) 9 | end 10 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/code_identifier_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule Code.IdentifierTest do 8 | use ExUnit.Case, async: true 9 | doctest Code.Identifier 10 | end 11 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/collectable_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule CollectableTest do 8 | use ExUnit.Case, async: true 9 | 10 | doctest Collectable 11 | end 12 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/at_exit.exs: -------------------------------------------------------------------------------- 1 | defmodule AtExit do 2 | def at_exit(str) do 3 | System.at_exit(fn _ -> IO.write(str) end) 4 | end 5 | end 6 | 7 | System.at_exit(fn status -> IO.puts("cruel world with status #{status}") end) 8 | AtExit.at_exit("goodbye ") 9 | exit({:shutdown, 1}) 10 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/code_sample.exs: -------------------------------------------------------------------------------- 1 | # Some Comments 2 | var = 1 + 2 3 | var 4 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/compile_sample.ex: -------------------------------------------------------------------------------- 1 | defmodule(CompileSample, do: nil) 2 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/bad_app.exs: -------------------------------------------------------------------------------- 1 | [sample: :oops] 2 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/bad_import.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | import_config "bad_root.exs" 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/env.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | config :my_app, env: config_env(), target: config_target() 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/good_config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | config :my_app, :key, :value 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/good_import.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | import_config "good_config.exs" 3 | :done 4 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/good_kw.exs: -------------------------------------------------------------------------------- 1 | [my_app: [key: :value]] 2 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/imports_recursive.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | import_config "recursive.exs" 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/kernel.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | config :kernel, :elixir_reboot, true 3 | config :elixir_reboot, :key, :value 4 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/nested.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | config :app, Repo, key: [nested: true] 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/configs/recursive.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | import_config "imports_recursive.exs" 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/consolidation/no_impl.ex: -------------------------------------------------------------------------------- 1 | defprotocol Protocol.ConsolidationTest.NoImpl do 2 | def ok(term) 3 | end 4 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/consolidation/sample.ex: -------------------------------------------------------------------------------- 1 | defprotocol Protocol.ConsolidationTest.Sample do 2 | @type t :: any 3 | @doc "Ok" 4 | @deprecated "Reason" 5 | @spec ok(t) :: boolean 6 | def ok(term) 7 | 8 | # Not a protocol function. While this is not "officially" supported, 9 | # it does happen in practice, so we need to make sure we preserve 10 | # its signature. 11 | Kernel.def(regular_fun(term), do: term + 1) 12 | end 13 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/consolidation/with_any.ex: -------------------------------------------------------------------------------- 1 | defprotocol Protocol.ConsolidationTest.WithAny do 2 | @fallback_to_any true 3 | @doc "Ok" 4 | def ok(term, opts) 5 | end 6 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/cp_mode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/test/elixir/fixtures/cp_mode -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/cp_r/a/1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/test/elixir/fixtures/cp_r/a/1.txt -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/cp_r/a/a/2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/test/elixir/fixtures/cp_r/a/a/2.txt -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/cp_r/b/3.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/test/elixir/fixtures/cp_r/b/3.txt -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/assertions.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Assertions do 2 | import ExUnit.Assertions 3 | 4 | def assert_with_truthy_match do 5 | assert :ok = known_type_truthy() 6 | end 7 | 8 | def assert_with_truthy_value do 9 | assert known_type_truthy() 10 | end 11 | 12 | def assert_with_unknown_type do 13 | assert unknown_type_truthy() 14 | end 15 | 16 | def refute_with_falsy_value do 17 | refute known_type_falsy() 18 | end 19 | 20 | def refute_with_unknown_type do 21 | refute unknown_type_falsy() 22 | end 23 | 24 | def refute_with_operator(log) do 25 | refute log == "failure" 26 | end 27 | 28 | defp known_type_truthy, do: :ok 29 | defp known_type_falsy, do: nil 30 | 31 | @spec unknown_type_truthy :: any 32 | defp unknown_type_truthy, do: Enum.random([1, true, :ok]) 33 | @spec unknown_type_falsy :: any 34 | defp unknown_type_falsy, do: Enum.random([false, nil]) 35 | end 36 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/boolean_check.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.BooleanCheck do 2 | def and_check(arg) when is_boolean(arg) do 3 | arg and arg 4 | end 5 | 6 | def or_check(arg) when is_boolean(arg) do 7 | arg or arg 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/callback.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Callback do 2 | @callback required(atom) :: atom 3 | @callback required(list) :: list 4 | end 5 | 6 | defmodule Dialyzer.Callback.ImplAtom do 7 | @behaviour Dialyzer.Callback 8 | def required(:ok), do: :ok 9 | end 10 | 11 | defmodule Dialyzer.Callback.ImplList do 12 | @behaviour Dialyzer.Callback 13 | def required([a, b]), do: [b, a] 14 | end 15 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/cond.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Cond do 2 | def one_boolean do 3 | cond do 4 | true -> :ok 5 | end 6 | end 7 | 8 | def two_boolean do 9 | cond do 10 | List.flatten([]) == [] -> :ok 11 | true -> :ok 12 | end 13 | end 14 | 15 | def one_otherwise do 16 | cond do 17 | :otherwise -> :ok 18 | end 19 | end 20 | 21 | def two_otherwise do 22 | cond do 23 | List.flatten([]) == [] -> :ok 24 | :otherwise -> :ok 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/defmacrop.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Defmacrop do 2 | defmacrop good_macro(id) do 3 | quote do 4 | {:good, {:good_macro, unquote(id)}} 5 | end 6 | end 7 | 8 | def run() do 9 | good_macro("Not So Bad") 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/for_bitstring.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.ForBitstring do 2 | def foo() do 3 | for a <- 1..3, into: "", do: <> 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/for_boolean_check.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.ForBooleanCheck do 2 | def foo(enum, potential) when is_binary(potential) do 3 | for element <- enum, string = Atom.to_string(element), string == potential do 4 | element 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/is_struct.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.IsStruct do 2 | def map_literal_atom_literal() do 3 | is_struct(%Macro.Env{}, Macro.Env) 4 | end 5 | 6 | def arg_atom_literal(arg) do 7 | is_struct(arg, Macro.Env) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/macrocallback.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Macrocallback do 2 | @macrocallback required(atom) :: Macro.t() 3 | @macrocallback optional(atom) :: Macro.t() 4 | @optional_callbacks [optional: 1] 5 | end 6 | 7 | defmodule Dialyzer.Macrocallback.Impl do 8 | @behaviour Dialyzer.Macrocallback 9 | defmacro required(var), do: Macro.expand(var, __CALLER__) 10 | defmacro optional(var), do: Macro.expand(var, __CALLER__) 11 | end 12 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/raise.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Raise do 2 | defexception [:message] 3 | 4 | def exception_var() do 5 | ex = %Dialyzer.Raise{} 6 | raise ex 7 | end 8 | 9 | def exception_var(ex = %Dialyzer.Raise{}) do 10 | raise ex 11 | end 12 | 13 | def string_var() do 14 | string = "hello" 15 | raise string 16 | end 17 | 18 | def string_var(string) when is_binary(string) do 19 | raise string 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/remote_call.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.RemoteCall do 2 | _ = Application.load(:dialyzer) 3 | 4 | case Application.spec(:dialyzer, :vsn) do 5 | ~c(2.) ++ _ -> 6 | @dialyzer {:no_fail_call, [map_var: 0]} 7 | 8 | three when three < ~c(3.0.2) -> 9 | # regression introduced in 3.0 for map warnings fixed in 3.0.2 10 | @dialyzer {:no_match, [map_var: 0, mod_var: 0]} 11 | 12 | _ -> 13 | :ok 14 | end 15 | 16 | def map_var() do 17 | map = %{key: 1} 18 | map.key 19 | end 20 | 21 | def map_var(map) when is_map(map) do 22 | map.key 23 | end 24 | 25 | def mod_var() do 26 | module = String.to_atom("Elixir.Hello") 27 | module.fun() 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/rewrite.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Rewrite do 2 | def interpolation do 3 | "foo #{:a}" 4 | end 5 | 6 | def reverse do 7 | Enum.reverse(1..3) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/try.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.Try do 2 | def rescue_error do 3 | try do 4 | :erlang.error(:badarg) 5 | rescue 6 | e in ErlangError -> {:ok, e} 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/with.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.With do 2 | def with_else do 3 | with :ok <- ok_or_error(), 4 | :ok <- ok_or_other_error(), 5 | :ok <- ok_or_tuple_error(), 6 | :ok <- ok_or_tuple_list_error() do 7 | :ok 8 | else 9 | :error -> 10 | :error 11 | 12 | :other_error -> 13 | :other_error 14 | 15 | {:error, msg} when is_list(msg) or is_tuple(msg) -> 16 | :error 17 | 18 | {:error, msg} when is_list(msg) when is_tuple(msg) -> 19 | :error 20 | 21 | {:error, _msg} -> 22 | :error 23 | end 24 | end 25 | 26 | @spec ok_or_error() :: :ok | :error 27 | defp ok_or_error do 28 | Enum.random([:ok, :error]) 29 | end 30 | 31 | @spec ok_or_other_error() :: :ok | :other_error 32 | defp ok_or_other_error do 33 | Enum.random([:ok, :other_error]) 34 | end 35 | 36 | @spec ok_or_tuple_error() :: :ok | {:error, :err} 37 | defp ok_or_tuple_error do 38 | Enum.random([:ok, {:error, :err}]) 39 | end 40 | 41 | @spec ok_or_tuple_list_error() :: :ok | {:error, [:err]} 42 | defp ok_or_tuple_list_error do 43 | Enum.random([:ok, {:error, [:err]}]) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/with_no_return.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.WithNoReturn do 2 | def with_no_return(list) do 3 | no_return = fn -> throw(:no_return) end 4 | 5 | with [] <- list do 6 | :ok 7 | else 8 | # note: throwing here directly wouldn't be caught in the first place, 9 | # calling a no_return function is what could cause an issue. 10 | _ -> no_return.() 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/dialyzer/with_throwing_else.ex: -------------------------------------------------------------------------------- 1 | defmodule Dialyzer.WithThrowingElse do 2 | def with_throwing_else(map) do 3 | with {:ok, foo} <- Map.fetch(map, :foo), 4 | false <- Enum.empty?(foo) do 5 | foo 6 | else 7 | # several clauses but one is a no_return 8 | :error -> throw(:empty_map) 9 | true -> nil 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/file.bin: -------------------------------------------------------------------------------- 1 | LF 2 | CR CRLF 3 | LFCR 4 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/file.txt: -------------------------------------------------------------------------------- 1 | FOO 2 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/multiline_file.txt: -------------------------------------------------------------------------------- 1 | this is the first line 2 | this is the second line 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/utf16_be_bom.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/test/elixir/fixtures/utf16_be_bom.txt -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/utf16_le_bom.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/elixir/test/elixir/fixtures/utf16_le_bom.txt -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/utf8.txt: -------------------------------------------------------------------------------- 1 | Русский 2 | 日 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/fixtures/utf8_bom.txt: -------------------------------------------------------------------------------- 1 | Русский 2 | 日 3 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/function_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule DummyFunction do 8 | def function_with_arity_0 do 9 | true 10 | end 11 | 12 | def zero?(0), do: true 13 | def zero?(_), do: false 14 | end 15 | 16 | defmodule FunctionTest do 17 | use ExUnit.Case, async: true 18 | 19 | doctest Function 20 | import Function 21 | 22 | @information_keys_for_named [:type, :module, :arity, :name, :env] 23 | @information_keys_for_anonymous @information_keys_for_named ++ 24 | [:pid, :index, :new_index, :new_uniq, :uniq] 25 | 26 | describe "capture/3" do 27 | test "captures module functions with arity 0" do 28 | f = capture(DummyFunction, :function_with_arity_0, 0) 29 | 30 | assert is_function(f) 31 | end 32 | 33 | test "captures module functions with any arity" do 34 | f = capture(DummyFunction, :zero?, 1) 35 | 36 | assert is_function(f) 37 | assert f.(0) 38 | end 39 | end 40 | 41 | describe "info/1" do 42 | test "returns info for named captured functions" do 43 | f = &DummyFunction.zero?/1 44 | expected = [module: DummyFunction, name: :zero?, arity: 1, env: [], type: :external] 45 | 46 | result = info(f) 47 | 48 | assert expected == result 49 | end 50 | 51 | test "returns info for anonymous functions" do 52 | f = fn x -> x end 53 | 54 | result = info(f) 55 | 56 | for {key, _value} <- result do 57 | assert key in @information_keys_for_anonymous 58 | end 59 | end 60 | end 61 | 62 | describe "info/2" do 63 | test "returns info for every possible information key for named functions" do 64 | f = &DummyFunction.zero?/1 65 | 66 | for x <- @information_keys_for_named do 67 | assert {^x, _} = info(f, x) 68 | end 69 | end 70 | 71 | test "returns info for every possible information key for anonymous functions" do 72 | f = &DummyFunction.zero?/1 73 | 74 | for x <- @information_keys_for_anonymous do 75 | assert {^x, _} = info(f, x) 76 | end 77 | 78 | assert {:arity, 1} = info(f, :arity) 79 | end 80 | end 81 | 82 | describe "identity/1" do 83 | test "returns whatever it gets passed" do 84 | assert :hello = Function.identity(:hello) 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/kernel/charlist_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule CharlistTest do 8 | use ExUnit.Case, async: true 9 | 10 | test "heredoc" do 11 | assert __ENV__.line == 11 12 | 13 | assert ~c"foo\nbar\n" == ~c""" 14 | foo 15 | bar 16 | """ 17 | 18 | assert __ENV__.line == 18 19 | 20 | assert ~c"foo\nbar '''\n" == ~c""" 21 | foo 22 | bar \'\'\' 23 | """ 24 | end 25 | 26 | test "UTF-8" do 27 | assert length(~c" ゆんゆん") == 5 28 | end 29 | 30 | test "hex" do 31 | assert ~c"\x76" == ~c"v" 32 | assert ~c"\u00fF" == ~c"ÿ" 33 | assert ~c"\u{A}" == ~c"\n" 34 | assert ~c"\u{e9}" == ~c"é" 35 | assert ~c"\u{10F}" == [271] 36 | assert ~c"\u{10FF}" == [4351] 37 | assert ~c"\u{10FFF}" == [69631] 38 | assert ~c"\u{10FFFF}" == [1_114_111] 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/kernel/deprecated_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Kernel.DeprecatedTest do 8 | use ExUnit.Case 9 | 10 | import PathHelpers 11 | 12 | test "raises on invalid @deprecated" do 13 | assert_raise ArgumentError, ~r"should be a string with the reason", fn -> 14 | defmodule InvalidDeprecated do 15 | @deprecated 1.2 16 | def foo, do: :bar 17 | end 18 | end 19 | end 20 | 21 | test "takes into account deprecated from defaults" do 22 | defmodule DefaultDeprecated do 23 | @deprecated "reason" 24 | def foo(x \\ true), do: x 25 | end 26 | 27 | assert DefaultDeprecated.__info__(:deprecated) == [ 28 | {{:foo, 0}, "reason"}, 29 | {{:foo, 1}, "reason"} 30 | ] 31 | end 32 | 33 | test "add deprecated to __info__" do 34 | write_beam( 35 | defmodule SampleDeprecated do 36 | @deprecated "Use SampleDeprecated.bar/0 instead" 37 | def foo, do: true 38 | 39 | def bar, do: false 40 | end 41 | ) 42 | 43 | deprecated = [ 44 | {{:foo, 0}, "Use SampleDeprecated.bar/0 instead"} 45 | ] 46 | 47 | assert SampleDeprecated.__info__(:deprecated) == deprecated 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/kernel/macros_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Kernel.MacrosTest.Nested do 8 | defmacro value, do: 1 9 | 10 | defmacro do_identity!(do: x) do 11 | x 12 | end 13 | end 14 | 15 | defmodule Kernel.MacrosTest do 16 | use ExUnit.Case, async: true 17 | 18 | Kernel.MacrosTest.Nested = require Kernel.MacrosTest.Nested, as: Nested 19 | 20 | @spec my_macro :: Macro.t() 21 | defmacro my_macro do 22 | quote(do: 1 + 1) 23 | end 24 | 25 | @spec my_private_macro :: Macro.t() 26 | defmacrop my_private_macro do 27 | quote(do: 1 + 3) 28 | end 29 | 30 | defmacro my_macro_with_default(value \\ 5) do 31 | quote(do: 1 + unquote(value)) 32 | end 33 | 34 | defp by_two(x), do: x * 2 35 | 36 | defmacro my_macro_with_local(value) do 37 | value = by_two(by_two(value)) 38 | quote(do: 1 + unquote(value)) 39 | end 40 | 41 | defmacro my_macro_with_capture(value) do 42 | Enum.map(value, &by_two/1) 43 | end 44 | 45 | test "require" do 46 | assert Kernel.MacrosTest.Nested.value() == 1 47 | end 48 | 49 | test "require with alias" do 50 | assert Nested.value() == 1 51 | end 52 | 53 | test "local with private macro" do 54 | assert my_private_macro() == 4 55 | end 56 | 57 | test "local with defaults macro" do 58 | assert my_macro_with_default() == 6 59 | end 60 | 61 | test "local with local call" do 62 | assert my_macro_with_local(4) == 17 63 | end 64 | 65 | test "local with capture" do 66 | assert my_macro_with_capture([1, 2, 3]) == [2, 4, 6] 67 | end 68 | 69 | test "macros cannot be called dynamically" do 70 | x = String.to_atom("Elixir.Nested") 71 | assert_raise UndefinedFunctionError, fn -> x.func() end 72 | end 73 | 74 | test "macros with bang and do block have proper precedence" do 75 | import Kernel.MacrosTest.Nested 76 | 77 | assert (do_identity! do 78 | 1 79 | end) == 1 80 | 81 | assert (Kernel.MacrosTest.Nested.do_identity! do 82 | 1 83 | end) == 1 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/kernel/special_forms_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Kernel.SpecialFormsTest do 8 | use ExUnit.Case, async: true 9 | 10 | doctest Kernel.SpecialForms 11 | 12 | describe "cond" do 13 | test "does not leak variables for one clause" do 14 | x = 0 15 | 16 | cond do 17 | true -> 18 | x = 1 19 | x 20 | end 21 | 22 | assert x == 0 23 | end 24 | 25 | test "does not leak variables for one clause with non-boolean as catch-all" do 26 | x = 0 27 | 28 | cond do 29 | :otherwise -> 30 | x = 1 31 | x 32 | end 33 | 34 | assert x == 0 35 | end 36 | 37 | test "does not leak variables for multiple clauses" do 38 | x = 0 39 | 40 | cond do 41 | List.flatten([]) == [] -> 42 | x = 1 43 | x 44 | 45 | true -> 46 | x = 1 47 | x 48 | end 49 | 50 | assert x == 0 51 | end 52 | 53 | test "does not leak variables from conditions" do 54 | x = :not_nil 55 | 56 | result = 57 | cond do 58 | x = List.first([]) -> 59 | x 60 | 61 | true -> 62 | x 63 | end 64 | 65 | assert result == :not_nil 66 | end 67 | 68 | test "does not warn on non-boolean as catch-all" do 69 | cond do 70 | List.flatten([]) == [] -> :good 71 | :otherwise -> :also_good 72 | end 73 | end 74 | 75 | test "cond_clause error keeps line number in stacktrace" do 76 | try do 77 | cond do 78 | Process.get(:unused, false) -> :ok 79 | end 80 | rescue 81 | _ -> 82 | assert [{Kernel.SpecialFormsTest, _, _, meta} | _] = __STACKTRACE__ 83 | assert meta[:file] 84 | assert meta[:line] 85 | end 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/list/chars_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule List.Chars.AtomTest do 8 | use ExUnit.Case, async: true 9 | 10 | test "basic" do 11 | assert to_charlist(:foo) == ~c"foo" 12 | end 13 | 14 | test "true false nil" do 15 | assert to_charlist(false) == ~c"false" 16 | assert to_charlist(true) == ~c"true" 17 | assert to_charlist(nil) == ~c"" 18 | end 19 | end 20 | 21 | defmodule List.Chars.BitStringTest do 22 | use ExUnit.Case, async: true 23 | 24 | test "basic" do 25 | assert to_charlist("foo") == ~c"foo" 26 | end 27 | end 28 | 29 | defmodule List.Chars.NumberTest do 30 | use ExUnit.Case, async: true 31 | 32 | test "integer" do 33 | assert to_charlist(1) == ~c"1" 34 | end 35 | 36 | test "float" do 37 | assert to_charlist(1.0) == ~c"1.0" 38 | end 39 | end 40 | 41 | defmodule List.Chars.ListTest do 42 | use ExUnit.Case, async: true 43 | 44 | test "basic" do 45 | assert to_charlist([1, "b", 3]) == [1, "b", 3] 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/module/types/helpers_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | Code.require_file("type_helper.exs", __DIR__) 5 | 6 | defmodule Module.Types.HelpersTest do 7 | use ExUnit.Case, async: true 8 | import Module.Types.Helpers 9 | 10 | test "expr_to_string/1" do 11 | assert expr_to_string({1, 2}) == "{1, 2}" 12 | assert expr_to_string(quote(do: Foo.bar(arg))) == "Foo.bar(arg)" 13 | assert expr_to_string(quote(do: :erlang.band(a, b))) == "Bitwise.band(a, b)" 14 | assert expr_to_string(quote(do: :erlang.orelse(a, b))) == "a or b" 15 | assert expr_to_string(quote(do: :erlang."=:="(a, b))) == "a === b" 16 | assert expr_to_string(quote(do: :erlang.list_to_atom(a))) == "List.to_atom(a)" 17 | assert expr_to_string(quote(do: :maps.remove(a, b))) == "Map.delete(b, a)" 18 | assert expr_to_string(quote(do: :erlang.element(1, a))) == "elem(a, 0)" 19 | assert expr_to_string(quote(do: :erlang.element(:erlang.+(a, 1), b))) == "elem(b, a)" 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/port_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule PortTest do 8 | use ExUnit.Case, async: true 9 | 10 | test "info/1,2 with registered name" do 11 | {:ok, port} = :gen_udp.open(0) 12 | 13 | assert Port.info(port, :links) == {:links, [self()]} 14 | assert Port.info(port, :registered_name) == {:registered_name, []} 15 | 16 | Process.register(port, __MODULE__) 17 | 18 | assert Port.info(port, :registered_name) == {:registered_name, __MODULE__} 19 | 20 | :ok = :gen_udp.close(port) 21 | 22 | assert Port.info(port, :registered_name) == nil 23 | assert Port.info(port) == nil 24 | end 25 | 26 | # In contrast with other inlined functions, 27 | # it is important to test that monitor/1 is inlined, 28 | # this way we gain the monitor receive optimisation. 29 | test "monitor/1 is inlined" do 30 | assert expand(quote(do: Port.monitor(port())), __ENV__) == 31 | quote(do: :erlang.monitor(:port, port())) 32 | end 33 | 34 | defp expand(expr, env) do 35 | {expr, _, _} = :elixir_expand.expand(expr, :elixir_env.env_to_ex(env), env) 36 | expr 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/elixir/test/elixir/tuple_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("test_helper.exs", __DIR__) 6 | 7 | defmodule TupleTest do 8 | use ExUnit.Case, async: true 9 | 10 | doctest Tuple 11 | 12 | # Tuple-related functions in the Kernel module. 13 | 14 | test "Kernel.elem/2" do 15 | assert elem({:a, :b, :c}, 1) == :b 16 | end 17 | 18 | test "Kernel.put_elem/3" do 19 | assert put_elem({:a, :b, :c}, 1, :d) == {:a, :d, :c} 20 | end 21 | 22 | test "keyword syntax is supported in tuple literals" do 23 | assert {1, 2, three: :four} == {1, 2, [three: :four]} 24 | end 25 | 26 | test "optional comma is supported in tuple literals" do 27 | assert Code.eval_string("{1,}") == {{1}, []} 28 | assert Code.eval_string("{1, 2, 3,}") == {{1, 2, 3}, []} 29 | end 30 | 31 | test "partial application" do 32 | assert (&{&1, 2}).(1) == {1, 2} 33 | assert (&{&1, &2}).(1, 2) == {1, 2} 34 | assert (&{&2, &1}).(2, 1) == {1, 2} 35 | end 36 | 37 | # Tuple module 38 | # We check two variants of each function due to inlining. 39 | 40 | test "duplicate/2" do 41 | assert Tuple.duplicate(:foo, 0) == {} 42 | assert Tuple.duplicate(:foo, 3) == {:foo, :foo, :foo} 43 | 44 | mod = Tuple 45 | assert mod.duplicate(:foo, 0) == {} 46 | assert mod.duplicate(:foo, 3) == {:foo, :foo, :foo} 47 | end 48 | 49 | test "insert_at/3" do 50 | assert Tuple.insert_at({:bar, :baz}, 0, :foo) == {:foo, :bar, :baz} 51 | 52 | mod = Tuple 53 | assert mod.insert_at({:bar, :baz}, 0, :foo) == {:foo, :bar, :baz} 54 | end 55 | 56 | test "delete_at/2" do 57 | assert Tuple.delete_at({:foo, :bar, :baz}, 0) == {:bar, :baz} 58 | 59 | mod = Tuple 60 | assert mod.delete_at({:foo, :bar, :baz}, 0) == {:bar, :baz} 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/elixir/test/erlang/atom_test.erl: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | -module(atom_test). 6 | -export([kv/1]). 7 | -include_lib("eunit/include/eunit.hrl"). 8 | 9 | eval(Content) -> 10 | Quoted = elixir:'string_to_quoted!'(Content, 1, 1, <<"nofile">>, []), 11 | {Value, Binding, _} = elixir:eval_forms(Quoted, [], elixir:env_for_eval([])), 12 | {Value, Binding}. 13 | 14 | kv([{Key, nil}]) -> Key. 15 | 16 | atom_with_punctuation_test() -> 17 | {foo@bar, []} = eval(":foo@bar"), 18 | {'a?', []} = eval(":a?"), 19 | {'a!', []} = eval(":a!"), 20 | {'||', []} = eval(":||"), 21 | {'...', []} = eval(":..."). 22 | 23 | atom_quoted_call_test() -> 24 | {3, []} = eval("Kernel.\"+\"(1, 2)"). 25 | 26 | kv_with_quotes_test() -> 27 | {'foo bar', []} = eval(":atom_test.kv(\"foo bar\": nil)"). 28 | 29 | kv_with_interpolation_test() -> 30 | {'foo', []} = eval(":atom_test.kv(\"#{\"foo\"}\": nil)"), 31 | {'foo', []} = eval(":atom_test.kv(\"#{\"fo\"}o\": nil)"), 32 | {'foo', _} = eval("a = \"f\"; :atom_test.kv(\"#{a}#{\"o\"}o\": nil)"). 33 | 34 | quoted_atom_test() -> 35 | {'+', []} = eval(":\"+\""), 36 | {'foo bar', []} = eval(":\"foo bar\""). 37 | 38 | atom_with_interpolation_test() -> 39 | {foo, []} = eval(":\"f#{\"o\"}o\""), 40 | {foo, _} = eval("a=\"foo\"; :\"#{a}\""), 41 | {foo, _} = eval("a=\"oo\"; :\"f#{a}\""), 42 | {foo, _} = eval("a=\"fo\"; :\"#{a}o\""), 43 | {fof, _} = eval("a=\"f\"; :\"#{a}o#{a}\""). 44 | 45 | quoted_atom_chars_are_escaped_test() -> 46 | {'"', []} = eval(":\"\\\"\""). 47 | -------------------------------------------------------------------------------- /lib/elixir/test/erlang/test_helper.erl: -------------------------------------------------------------------------------- 1 | %% SPDX-License-Identifier: Apache-2.0 2 | %% SPDX-FileCopyrightText: 2021 The Elixir Team 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | -module(test_helper). 6 | -export([test/0, run_and_remove/2, throw_elixir/1, throw_erlang/1]). 7 | -define(TESTS, [ 8 | atom_test, 9 | control_test, 10 | function_test, 11 | string_test, 12 | tokenizer_test 13 | ]). 14 | 15 | test() -> 16 | application:ensure_all_started(elixir), 17 | case eunit:test(?TESTS) of 18 | error -> erlang:halt(1); 19 | _Res -> erlang:halt(0) 20 | end. 21 | 22 | % Execute a piece of code and purge given modules right after 23 | run_and_remove(Fun, Modules) -> 24 | try 25 | Fun() 26 | after 27 | [code:purge(Module) || Module <- Modules], 28 | [code:delete(Module) || Module <- Modules] 29 | end. 30 | 31 | % Throws an error with the Erlang Abstract Form from the Elixir string 32 | throw_elixir(String) -> 33 | Forms = elixir:'string_to_quoted!'(String, 1, 1, <<"nofile">>, []), 34 | {Expr, _, _, _} = elixir:quoted_to_erl(Forms, elixir:env_for_eval([])), 35 | erlang:error(io:format("~p~n", [Expr])). 36 | 37 | % Throws an error with the Erlang Abstract Form from the Erlang string 38 | throw_erlang(String) -> 39 | {ok, Tokens, _} = erl_scan:string(String), 40 | {ok, [Form]} = erl_parse:parse_exprs(Tokens), 41 | erlang:error(io:format("~p~n", [Form])). 42 | -------------------------------------------------------------------------------- /lib/ex_unit/lib/ex_unit/on_exit_handler/supervisor.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | defmodule ExUnit.OnExitHandler.Supervisor do 5 | @moduledoc false 6 | use Supervisor 7 | 8 | def start_link(children) do 9 | Supervisor.start_link(__MODULE__, {children, get_callers(self())}) 10 | end 11 | 12 | @impl true 13 | def init({children, callers}) do 14 | put_callers(callers) 15 | Supervisor.init(children, strategy: :one_for_one, max_restarts: 1_000_000, max_seconds: 1) 16 | end 17 | 18 | defp get_callers(owner) do 19 | case :erlang.get(:"$callers") do 20 | [_ | _] = list -> [owner | list] 21 | _ -> [owner] 22 | end 23 | end 24 | 25 | defp put_callers(callers) do 26 | :erlang.put(:"$callers", callers) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/ex_unit/mix.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule ExUnit.MixProject do 6 | use Mix.Project 7 | 8 | def project do 9 | [ 10 | app: :ex_unit, 11 | version: System.version(), 12 | build_per_environment: false 13 | ] 14 | end 15 | 16 | def application do 17 | [ 18 | registered: [ExUnit.CaptureServer, ExUnit.OnExitHandler, ExUnit.Server, ExUnit.Supervisor], 19 | mod: {ExUnit, []}, 20 | env: [ 21 | # Calculated on demand 22 | # max_cases: System.schedulers_online * 2, 23 | # seed: rand(), 24 | 25 | assert_receive_timeout: 100, 26 | autorun: true, 27 | capture_log: false, 28 | colors: [], 29 | exclude: [], 30 | exit_status: 2, 31 | formatters: [ExUnit.CLIFormatter], 32 | include: [], 33 | max_failures: :infinity, 34 | rand_algorithm: :exsss, 35 | refute_receive_timeout: 100, 36 | slowest: 0, 37 | slowest_modules: 0, 38 | stacktrace_depth: 20, 39 | timeout: 60000, 40 | trace: false, 41 | after_suite: [], 42 | repeat_until_failure: 0 43 | ] 44 | ] 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/ex_unit/test/ex_unit/case_template_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule ExUnit.SampleCase do 8 | use ExUnit.CaseTemplate 9 | 10 | using _ do 11 | quote do 12 | import unquote(__MODULE__) 13 | end 14 | end 15 | 16 | def hello do 17 | "world" 18 | end 19 | 20 | setup_all do 21 | {:ok, [context: :setup_all, setup_all: 1]} 22 | end 23 | 24 | setup context do 25 | assert context[:context] == :setup_all 26 | {:ok, [context: :setup, setup: 1]} 27 | end 28 | end 29 | 30 | defmodule ExUnit.NestedCase do 31 | use ExUnit.CaseTemplate 32 | 33 | setup_all context do 34 | {:ok, [setup_all: context[:setup_all] + 1]} 35 | end 36 | 37 | setup context do 38 | {:ok, [setup: context[:setup] + 1]} 39 | end 40 | end 41 | 42 | defmodule ExUnit.CaseTemplateTest do 43 | use ExUnit.SampleCase, async: true, another_option: 123 44 | use ExUnit.NestedCase 45 | 46 | two = 2 47 | 48 | test "unquoting the value #{two}" do 49 | assert 2 == unquote(two) 50 | end 51 | 52 | test "receives context from parent case", %{context: context} do 53 | assert context == :setup 54 | end 55 | 56 | test "runs both templates setup", context do 57 | assert context[:setup] == 2 58 | end 59 | 60 | test "runs both templates setup_all", context do 61 | assert context[:setup_all] == 2 62 | end 63 | 64 | test "using code is executed" do 65 | assert hello() == "world" 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/ex_unit/test/fixtures/failing.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | iex> 1 + 2 4 | 4 5 | -------------------------------------------------------------------------------- /lib/ex_unit/test/fixtures/passing.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | iex> 1 + 2 4 | 3 5 | 6 | iex> 2 + 3 7 | 5 8 | -------------------------------------------------------------------------------- /lib/ex_unit/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Logger.configure_backend(:console, colors: [enabled: false]) 6 | 7 | {line_exclude, line_include} = 8 | if line = System.get_env("LINE"), do: {[:test], [line: line]}, else: {[], []} 9 | 10 | Code.require_file("../../elixir/scripts/cover_record.exs", __DIR__) 11 | CoverageRecorder.maybe_record("ex_unit") 12 | 13 | ExUnit.start( 14 | trace: !!System.get_env("TRACE"), 15 | include: line_include, 16 | exclude: line_exclude, 17 | assert_receive_timeout: String.to_integer(System.get_env("ELIXIR_ASSERT_TIMEOUT", "300")) 18 | ) 19 | -------------------------------------------------------------------------------- /lib/iex/lib/iex/app.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule IEx.App do 6 | @moduledoc false 7 | 8 | use Application 9 | 10 | def start(_type, _args) do 11 | with :default <- Application.get_env(:stdlib, :shell_multiline_prompt, :default) do 12 | Application.put_env(:stdlib, :shell_multiline_prompt, {IEx.Config, :prompt}) 13 | end 14 | 15 | children = [IEx.Config, IEx.Broker, IEx.Pry] 16 | Supervisor.start_link(children, strategy: :one_for_one, name: IEx.Supervisor) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/iex/lib/iex/mix_listener.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | defmodule IEx.MixListener do 5 | @moduledoc false 6 | 7 | use GenServer 8 | 9 | @name __MODULE__ 10 | 11 | @spec start_link(keyword) :: GenServer.on_start() 12 | def start_link(_opts) do 13 | GenServer.start_link(__MODULE__, {}, name: @name) 14 | end 15 | 16 | @doc """ 17 | Unloads all modules invalidated by external compilations. 18 | 19 | Returns `:noop` if there is no module to purge or if 20 | the listener is not running (it may happen when connecting 21 | via --remsh to a node that was started without IEx). 22 | """ 23 | @spec purge :: :ok | :noop 24 | def purge do 25 | if Process.whereis(@name) do 26 | GenServer.call(@name, :purge, :infinity) 27 | else 28 | :noop 29 | end 30 | end 31 | 32 | @impl true 33 | def init({}) do 34 | {:ok, %{to_purge: MapSet.new()}} 35 | end 36 | 37 | @impl true 38 | def handle_call(:purge, _from, state) do 39 | purge_modules(state.to_purge) 40 | status = if Enum.empty?(state.to_purge), do: :noop, else: :ok 41 | {:reply, status, %{state | to_purge: MapSet.new()}} 42 | end 43 | 44 | @impl true 45 | def handle_info({:modules_compiled, info}, state) do 46 | if info.os_pid == System.pid() do 47 | # Ignore compilations from ourselves, because the modules are 48 | # already updated in memory 49 | {:noreply, state} 50 | else 51 | %{changed: changed, removed: removed} = info.modules_diff 52 | 53 | if IEx.Config.auto_reload?() do 54 | purge_modules(changed) 55 | purge_modules(removed) 56 | {:noreply, state} 57 | else 58 | state = update_in(state.to_purge, &Enum.into(changed, &1)) 59 | state = update_in(state.to_purge, &Enum.into(removed, &1)) 60 | {:noreply, state} 61 | end 62 | end 63 | end 64 | 65 | def handle_info(_message, state) do 66 | {:noreply, state} 67 | end 68 | 69 | defp purge_modules(modules) do 70 | for module <- modules do 71 | :code.purge(module) 72 | :code.delete(module) 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/iex/mix.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule IEx.MixProject do 6 | use Mix.Project 7 | 8 | def project do 9 | [ 10 | app: :iex, 11 | version: System.version(), 12 | build_per_environment: false 13 | ] 14 | end 15 | 16 | def application do 17 | [ 18 | registered: [IEx.Broker, IEx.Config, IEx.Pry, IEx.Supervisor], 19 | mod: {IEx.App, []}, 20 | env: [ 21 | colors: [], 22 | parser: {IEx.Evaluator, :parse, []}, 23 | inspect: [pretty: true], 24 | history_size: 20, 25 | default_prompt: "%prefix(%counter)>", 26 | alive_prompt: "%prefix(%node)%counter>", 27 | auto_reload: false 28 | ] 29 | ] 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/iex/test/iex/config_test.exs: -------------------------------------------------------------------------------- 1 | Code.require_file("../test_helper.exs", __DIR__) 2 | 3 | defmodule IEx.ConfigTest do 4 | use ExUnit.Case, async: true 5 | 6 | import IEx.Config 7 | 8 | describe "prompt" do 9 | test "converts everything before opening parens to dots" do 10 | assert prompt(~c"iex(321)>") == ~c"...(321)>" 11 | assert prompt(~c"foo-bar(321)>") == ~c".......(321)>" 12 | end 13 | 14 | test "falls back to Erlang wit no parens around" do 15 | assert prompt(~c"foo-bar>") == ~c" .. " 16 | end 17 | 18 | test "ignores ansi escapes" do 19 | assert prompt(~c"#{IO.ANSI.red()}iex(foo)>") == ~c"...(foo)>" 20 | assert prompt(~c"#{IO.ANSI.red()}foo-bar>") == ~c" .. " 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/logger/lib/logger/backends/supervisor.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Logger.Backends.Supervisor do 6 | @moduledoc false 7 | use Supervisor 8 | 9 | @name __MODULE__ 10 | 11 | def add(backend) do 12 | spec = %{ 13 | id: backend, 14 | start: {Logger.Backends.Watcher, :start_link, [{backend, backend}]}, 15 | restart: :transient 16 | } 17 | 18 | case Supervisor.start_child(@name, spec) do 19 | {:error, :already_present} -> 20 | _ = Supervisor.delete_child(@name, backend) 21 | add(backend) 22 | 23 | other -> 24 | other 25 | end 26 | end 27 | 28 | def remove(backend) do 29 | case Supervisor.terminate_child(@name, backend) do 30 | :ok -> 31 | _ = Supervisor.delete_child(@name, backend) 32 | :ok 33 | 34 | {:error, _} = error -> 35 | error 36 | end 37 | end 38 | 39 | def start_link(backends) do 40 | case Supervisor.start_link(__MODULE__, [], name: @name) do 41 | {:ok, _} = ok -> 42 | for backend <- backends do 43 | case add(backend) do 44 | {:ok, _} -> 45 | :ok 46 | 47 | {:error, {{:EXIT, exit}, _spec}} -> 48 | raise "EXIT when installing backend #{inspect(backend)}: " <> 49 | Exception.format_exit(exit) 50 | 51 | {:error, error} -> 52 | raise "ERROR when installing backend #{inspect(backend)}: " <> 53 | Exception.format_exit(error) 54 | end 55 | end 56 | 57 | ok 58 | 59 | {:error, _} = error -> 60 | error 61 | end 62 | end 63 | 64 | @impl true 65 | def init(children) do 66 | Supervisor.init(children, strategy: :one_for_one, max_restarts: 30, max_seconds: 3) 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /lib/logger/lib/logger/backends/watcher.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Logger.Backends.Watcher do 6 | @moduledoc false 7 | require Logger 8 | use GenServer 9 | 10 | @doc false 11 | def start_link(tuple) do 12 | GenServer.start_link(__MODULE__, tuple) 13 | end 14 | 15 | @impl true 16 | def init({handler, args}) do 17 | Process.flag(:trap_exit, true) 18 | 19 | case :gen_event.delete_handler(Logger, handler, :ok) do 20 | {:error, :module_not_found} -> 21 | case :gen_event.add_sup_handler(Logger, handler, args) do 22 | :ok -> 23 | {:ok, handler} 24 | 25 | {:error, :ignore} -> 26 | # Can't return :ignore as a transient child under a one_for_one. 27 | # Instead return ok and then immediately exit normally - using a fake 28 | # message. 29 | send(self(), {:gen_event_EXIT, handler, :normal}) 30 | {:ok, handler} 31 | 32 | {:error, reason} -> 33 | {:stop, reason} 34 | 35 | {:EXIT, _} = exit -> 36 | {:stop, exit} 37 | end 38 | 39 | _ -> 40 | init({handler, args}) 41 | end 42 | end 43 | 44 | @impl true 45 | def handle_info({:gen_event_EXIT, handler, reason}, handler) 46 | when reason in [:normal, :shutdown] do 47 | {:stop, reason, handler} 48 | end 49 | 50 | def handle_info({:gen_event_EXIT, handler, reason}, handler) do 51 | message = [ 52 | ":gen_event handler ", 53 | inspect(handler), 54 | " installed in Logger terminating\n", 55 | "** (exit) ", 56 | format_exit(reason) 57 | ] 58 | 59 | cond do 60 | logger_has_backends?() -> :ok 61 | true -> IO.puts(:stderr, message) 62 | end 63 | 64 | {:stop, reason, handler} 65 | end 66 | 67 | def handle_info(_msg, state) do 68 | {:noreply, state} 69 | end 70 | 71 | defp logger_has_backends?() do 72 | try do 73 | :gen_event.which_handlers(Logger) != [Logger.Backends.Config] 74 | catch 75 | _, _ -> false 76 | end 77 | end 78 | 79 | @impl true 80 | def terminate(_reason, handler) do 81 | # On terminate we remove the handler, this makes the 82 | # process sync, allowing existing messages to be flushed 83 | :gen_event.delete_handler(Logger, handler, :ok) 84 | :ok 85 | end 86 | 87 | defp format_exit({:EXIT, reason}), do: Exception.format_exit(reason) 88 | defp format_exit(reason), do: Exception.format_exit(reason) 89 | end 90 | -------------------------------------------------------------------------------- /lib/logger/mix.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Logger.MixProject do 6 | use Mix.Project 7 | 8 | def project do 9 | [ 10 | app: :logger, 11 | version: System.version(), 12 | build_per_environment: false 13 | ] 14 | end 15 | 16 | def application do 17 | [ 18 | registered: [Logger, Logger.Supervisor], 19 | mod: {Logger.App, []}, 20 | env: [ 21 | utc_log: false, 22 | truncate: 8096, 23 | translators: [{Logger.Translator, :translate}], 24 | handle_otp_reports: true, 25 | handle_sasl_reports: false, 26 | always_evaluate_messages: false, 27 | compile_time_purge_matching: [], 28 | compile_time_application: nil, 29 | translator_inspect_opts: [], 30 | start_options: [], 31 | sync_threshold: 20, 32 | discard_threshold: 500, 33 | discard_threshold_periodic_check: 30_000, 34 | metadata: [] 35 | ] 36 | ] 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/logger/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | {line_exclude, line_include} = 6 | if line = System.get_env("LINE"), do: {[:test], [line: line]}, else: {[], []} 7 | 8 | Code.require_file("../../elixir/scripts/cover_record.exs", __DIR__) 9 | CoverageRecorder.maybe_record("logger") 10 | 11 | ExUnit.start( 12 | trace: !!System.get_env("TRACE"), 13 | include: line_include, 14 | exclude: line_exclude, 15 | assert_receive_timeout: String.to_integer(System.get_env("ELIXIR_ASSERT_TIMEOUT", "300")) 16 | ) 17 | 18 | defmodule Logger.Case do 19 | use ExUnit.CaseTemplate 20 | import ExUnit.CaptureIO 21 | 22 | using _ do 23 | quote do 24 | import Logger.Case 25 | end 26 | end 27 | 28 | def msg(msg) do 29 | ~r/\d\d\:\d\d\:\d\d\.\d\d\d #{Regex.escape(msg)}/ 30 | end 31 | 32 | def wait_for_handler(manager, handler) do 33 | if handler not in :gen_event.which_handlers(manager) do 34 | Process.sleep(10) 35 | wait_for_handler(manager, handler) 36 | end 37 | end 38 | 39 | def wait_for_logger() do 40 | try do 41 | :gen_event.which_handlers(Logger) 42 | catch 43 | :exit, _ -> 44 | Process.sleep(10) 45 | wait_for_logger() 46 | else 47 | _ -> 48 | :ok 49 | end 50 | end 51 | 52 | def capture_log(level \\ :debug, fun) do 53 | Logger.configure(level: level) 54 | 55 | capture_io(:user, fn -> 56 | fun.() 57 | Logger.flush() 58 | end) 59 | after 60 | Logger.configure(level: :debug) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/dep/elixir_scm.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | # Manifest file where we treat Elixir and SCMs as a dependency. 6 | defmodule Mix.Dep.ElixirSCM do 7 | @moduledoc false 8 | @manifest "compile.elixir_scm" 9 | @manifest_vsn 1 10 | 11 | def manifest(manifest_path \\ Mix.Project.manifest_path()) do 12 | Path.join(manifest_path, @manifest) 13 | end 14 | 15 | def update(manifest_path \\ Mix.Project.manifest_path()) do 16 | config = Mix.Project.config() 17 | File.mkdir_p!(manifest_path) 18 | 19 | manifest_data = 20 | {@manifest_vsn, {System.version(), :erlang.system_info(:otp_release)}, config[:build_scm]} 21 | |> :erlang.term_to_binary() 22 | 23 | File.write!(manifest(manifest_path), manifest_data) 24 | end 25 | 26 | def read(manifest_path \\ Mix.Project.manifest_path()) do 27 | case File.read(manifest(manifest_path)) do 28 | {:ok, contents} -> 29 | try do 30 | {@manifest_vsn, vsn, scm} = :erlang.binary_to_term(contents) 31 | {:ok, vsn, scm} 32 | rescue 33 | _ -> {:ok, {"1.0.0", ~c"17"}, nil} 34 | end 35 | 36 | _ -> 37 | :error 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/dep/lock.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | # This module keeps a lock file and the manifest for the lock file. 6 | # The lockfile keeps the latest dependency information while the 7 | # manifest is used whenever a dependency is affected via any of the 8 | # deps.* tasks. We also keep the Elixir version in the manifest file. 9 | defmodule Mix.Dep.Lock do 10 | @moduledoc false 11 | 12 | @doc """ 13 | Reads the lockfile, returns a map containing 14 | each app name and its current lock information. 15 | """ 16 | @spec read(Path.t()) :: map() 17 | def read(lockfile \\ lockfile()) do 18 | opts = [file: lockfile, emit_warnings: false] 19 | 20 | with {:ok, contents} <- File.read(lockfile), 21 | assert_no_merge_conflicts_in_lockfile(lockfile, contents), 22 | {:ok, quoted} <- Code.string_to_quoted(contents, opts), 23 | {%{} = lock, _binding} <- Code.eval_quoted(quoted, [], opts) do 24 | lock 25 | else 26 | _ -> %{} 27 | end 28 | end 29 | 30 | @doc """ 31 | Receives a map and writes it as the latest lock. 32 | """ 33 | @spec write(map(), keyword) :: :ok 34 | def write(map, opts \\ []) do 35 | lockfile = opts[:file] || lockfile() 36 | 37 | if map != read() do 38 | if Keyword.get(opts, :check_locked, false) do 39 | Mix.raise( 40 | "Your #{lockfile} is out of date and must be updated without the --check-locked flag" 41 | ) 42 | end 43 | 44 | lines = 45 | for {app, rev} <- Enum.sort(map), rev != nil do 46 | ~s( "#{app}": #{inspect(rev, limit: :infinity)},\n) 47 | end 48 | 49 | File.write!(lockfile, ["%{\n", lines, "}\n"]) 50 | Mix.Task.run("will_recompile") 51 | end 52 | 53 | :ok 54 | end 55 | 56 | defp lockfile do 57 | Mix.Project.config()[:lockfile] 58 | end 59 | 60 | defp assert_no_merge_conflicts_in_lockfile(lockfile, info) do 61 | if String.contains?(info, ~w(<<<<<<< ======= >>>>>>>)) do 62 | Mix.raise( 63 | "Your #{lockfile} contains merge conflicts. Please resolve the conflicts " <> 64 | "and run the command again" 65 | ) 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/dep/umbrella.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Dep.Umbrella do 6 | @moduledoc false 7 | 8 | @doc """ 9 | Gets all umbrella dependencies in unloaded format. 10 | """ 11 | def unloaded do 12 | config = Mix.Project.config() 13 | 14 | if apps_paths = Mix.Project.apps_paths(config) do 15 | env = Mix.env() 16 | from = Path.absname("mix.exs") 17 | build = Mix.Project.build_path(config) 18 | 19 | for {app, path} <- apps_paths do 20 | dest_path = Path.expand(path) 21 | build_path = Path.join([build, "lib", Atom.to_string(app)]) 22 | 23 | opts = [ 24 | path: path, 25 | dest: dest_path, 26 | from_umbrella: true, 27 | env: env, 28 | build: build_path 29 | ] 30 | 31 | %Mix.Dep{ 32 | scm: Mix.SCM.Path, 33 | app: app, 34 | requirement: nil, 35 | manager: :mix, 36 | status: {:ok, nil}, 37 | from: from, 38 | opts: opts 39 | } 40 | end 41 | else 42 | [] 43 | end 44 | end 45 | 46 | @doc """ 47 | Gets all umbrella dependencies in the loaded format from cache (if available). 48 | """ 49 | def cached do 50 | if project = Mix.Project.get() do 51 | key = {:umbrella_deps, Mix.env(), project} 52 | Mix.State.read_cache(key) || Mix.State.write_cache(key, loaded()) 53 | else 54 | loaded() 55 | end 56 | end 57 | 58 | @doc """ 59 | Gets all umbrella dependencies in the loaded format. 60 | """ 61 | def loaded do 62 | deps = unloaded() 63 | apps = Enum.map(deps, & &1.app) 64 | 65 | Enum.map(deps, fn umbrella_dep -> 66 | umbrella_dep = Mix.Dep.Loader.load(umbrella_dep, nil, false) 67 | 68 | deps = 69 | Enum.filter(umbrella_dep.deps, fn dep -> 70 | Mix.Dep.available?(dep) and dep.app in apps 71 | end) 72 | 73 | %{umbrella_dep | deps: deps} 74 | end) 75 | |> Mix.Dep.Converger.topological_sort() 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/hex.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Hex do 6 | @moduledoc false 7 | @compile {:no_warn_undefined, Hex} 8 | @hex_requirement ">= 2.0.6" 9 | @hex_builds_url "https://builds.hex.pm" 10 | 11 | @doc """ 12 | Returns `true` if `Hex` is loaded or installed. 13 | 14 | Otherwise returns `false`. 15 | """ 16 | @spec ensure_installed?(boolean) :: boolean 17 | def ensure_installed?(force?) do 18 | cond do 19 | Code.ensure_loaded?(Hex) -> true 20 | force? or install_hex?() -> Mix.Tasks.Local.Hex.run(["--force"]) 21 | true -> false 22 | end 23 | end 24 | 25 | defp install_hex? do 26 | shell = Mix.shell() 27 | shell.info("Mix requires the Hex package manager to fetch dependencies") 28 | 29 | shell.yes?( 30 | "Shall I install Hex? (if running non-interactively, use \"mix local.hex --force\")" 31 | ) 32 | end 33 | 34 | @doc """ 35 | Returns `true` if it has the required `Hex`. If an update is performed, it then exits. 36 | Otherwise returns `false` without updating anything. 37 | """ 38 | @spec ensure_updated?() :: boolean 39 | def ensure_updated?() do 40 | cond do 41 | not Code.ensure_loaded?(Hex) -> 42 | false 43 | 44 | not Version.match?(Hex.version(), @hex_requirement) -> 45 | Mix.shell().info("Mix requires Hex #{@hex_requirement} but you have #{Hex.version()}") 46 | 47 | if Mix.shell().yes?("Shall I abort the current command and update Hex?") do 48 | Mix.Tasks.Local.Hex.run(["--force"]) 49 | exit({:shutdown, 0}) 50 | end 51 | 52 | false 53 | 54 | true -> 55 | true 56 | end 57 | end 58 | 59 | @doc """ 60 | Ensures `Hex` is started. 61 | """ 62 | def start do 63 | try do 64 | Hex.start() 65 | catch 66 | kind, reason -> 67 | Mix.shell().error( 68 | "Could not start Hex. Try fetching a new version with " <> 69 | "\"mix local.hex\" or uninstalling it with \"mix archive.uninstall hex.ez\"" 70 | ) 71 | 72 | :erlang.raise(kind, reason, __STACKTRACE__) 73 | end 74 | end 75 | 76 | @doc """ 77 | Returns the URL to the Hex build assets. 78 | """ 79 | def url do 80 | System.get_env("HEX_BUILDS_URL") || System.get_env("HEX_MIRROR") || @hex_builds_url 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/pubsub/subscriber.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | defmodule Mix.PubSub.Subscriber do 5 | @moduledoc false 6 | 7 | use GenServer 8 | 9 | @name __MODULE__ 10 | 11 | @spec start_link(keyword) :: GenServer.on_start() 12 | def start_link(_opts) do 13 | GenServer.start_link(__MODULE__, {}, name: @name) 14 | end 15 | 16 | @spec flush :: :ok 17 | def flush do 18 | GenServer.cast(@name, :flush) 19 | end 20 | 21 | @impl true 22 | def init({}) do 23 | build_path = Mix.Project.build_path() 24 | Mix.Sync.PubSub.subscribe(build_path) 25 | {:ok, %{acc: []}} 26 | end 27 | 28 | @impl true 29 | def handle_info(message, %{acc: nil} = state) do 30 | notify_listeners([message]) 31 | {:noreply, state} 32 | end 33 | 34 | def handle_info(message, state) do 35 | # Accumulate messages until the flush 36 | {:noreply, update_in(state.acc, &[message | &1])} 37 | end 38 | 39 | @impl true 40 | def handle_cast(:flush, state) do 41 | notify_listeners(Enum.reverse(state.acc)) 42 | {:noreply, %{state | acc: nil}} 43 | end 44 | 45 | defp notify_listeners(messages) do 46 | children = Supervisor.which_children(Mix.PubSub.ListenerSupervisor) 47 | 48 | for message <- messages do 49 | for {_, pid, _, _} <- children, is_pid(pid) do 50 | send(pid, message) 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/remote_converger.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.RemoteConverger do 6 | @moduledoc false 7 | 8 | # A remote converger returns updated dependencies with 9 | # extra information that can be used during Mix's converging. 10 | # Useful for things like external package managers 11 | 12 | @doc """ 13 | Returns `true` if given dependency is handled by 14 | remote converger. 15 | """ 16 | @callback remote?(Mix.Dep.t()) :: boolean 17 | 18 | @doc """ 19 | Runs the remote converger. 20 | 21 | Return updated lock. 22 | """ 23 | @callback converge([Mix.Dep.t()], map) :: map 24 | 25 | @doc """ 26 | Returns child dependencies the converger has for the 27 | dependency. This list should filter the loaded children. 28 | """ 29 | @callback deps(Mix.Dep.t(), map) :: [atom] 30 | 31 | @doc """ 32 | Called after all convergers have run so that the remote 33 | converger can perform cleanup. 34 | """ 35 | @callback post_converge() :: any 36 | 37 | @doc """ 38 | Gets registered remote converger. 39 | """ 40 | def get do 41 | Mix.State.get(:remote_converger) 42 | end 43 | 44 | @doc """ 45 | Registers a remote converger. 46 | """ 47 | def register(mod) when is_atom(mod) do 48 | Mix.State.put(:remote_converger, mod) 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/scm/path.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.SCM.Path do 6 | @behaviour Mix.SCM 7 | @moduledoc false 8 | 9 | @impl true 10 | def fetchable? do 11 | false 12 | end 13 | 14 | @impl true 15 | def format(opts) do 16 | opts[:path] 17 | end 18 | 19 | @impl true 20 | def format_lock(_opts) do 21 | nil 22 | end 23 | 24 | @impl true 25 | def accepts_options(app, opts) do 26 | cond do 27 | raw = opts[:path] -> 28 | Keyword.put(opts, :dest, Path.expand(raw)) 29 | 30 | opts[:in_umbrella] -> 31 | if opts[:override] do 32 | Mix.shell().error(""" 33 | warning: in-umbrella application #{inspect(app)} has the flag :override \ 34 | set to true, but the flag has no effect when running from the umbrella root 35 | """) 36 | end 37 | 38 | if opts[:optional] do 39 | Mix.shell().error(""" 40 | warning: in-umbrella application #{inspect(app)} has the flag :optional \ 41 | set to true, but the flag is not supported for umbrella dependencies 42 | """) 43 | end 44 | 45 | path = "../#{app}" 46 | 47 | opts 48 | |> Keyword.put(:dest, Path.expand(path)) 49 | |> Keyword.put_new(:path, path) 50 | |> Keyword.put_new(:env, Mix.env()) 51 | 52 | true -> 53 | nil 54 | end 55 | end 56 | 57 | @impl true 58 | def checked_out?(opts) do 59 | File.dir?(opts[:dest]) 60 | end 61 | 62 | @impl true 63 | def lock_status(_opts) do 64 | :ok 65 | end 66 | 67 | @impl true 68 | def equal?(opts1, opts2) do 69 | opts1[:dest] == opts2[:dest] 70 | end 71 | 72 | @impl true 73 | def managers(_opts) do 74 | [] 75 | end 76 | 77 | @impl true 78 | def checkout(opts) do 79 | path = Path.relative_to_cwd(opts[:dest]) 80 | Mix.raise("Cannot checkout path dependency, expected a dependency at #{path}") 81 | end 82 | 83 | @impl true 84 | def update(opts) do 85 | opts[:lock] 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/shell/quiet.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Shell.Quiet do 6 | @moduledoc """ 7 | This is Mix's default shell when the `MIX_QUIET` environment 8 | variable is set. 9 | 10 | It's just like `Mix.Shell.IO`, but prints far less. 11 | """ 12 | 13 | @behaviour Mix.Shell 14 | 15 | @doc """ 16 | Prints the current application if it 17 | was not printed yet. 18 | """ 19 | defdelegate print_app, to: Mix.Shell.IO 20 | 21 | @doc """ 22 | Prints nothing to the shell. 23 | """ 24 | def info(_message), do: :ok 25 | 26 | @doc """ 27 | Prints the error to the shell followed by a newline. 28 | """ 29 | defdelegate error(message), to: Mix.Shell.IO 30 | 31 | @doc """ 32 | Prints a message and prompts the user for input. 33 | 34 | Input will be consumed until Enter is pressed. 35 | """ 36 | defdelegate prompt(message), to: Mix.Shell.IO 37 | 38 | @doc """ 39 | Prints a message and asks the user to confirm if they 40 | want to proceed. The user must type and submit one of 41 | "y", "yes", "Y", "YES" or "Yes". 42 | 43 | The user may also press Enter; this can be configured 44 | to either accept or reject the prompt. The latter case 45 | may be useful for a potentially dangerous operation that 46 | should require explicit confirmation from the user. 47 | 48 | ## Options 49 | 50 | * `:default` - (:yes or :no) if `:yes` pressing Enter 51 | accepts the prompt; if `:no` pressing Enter rejects 52 | the prompt instead. Defaults to `:yes`. 53 | 54 | """ 55 | defdelegate yes?(message, options \\ []), to: Mix.Shell.IO 56 | 57 | @doc """ 58 | Executes the given command quietly without outputting anything. 59 | """ 60 | def cmd(command, opts \\ []) do 61 | Mix.Shell.cmd(command, opts, fn data -> data end) 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/archive.check.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Archive.Check do 6 | use Mix.Task 7 | 8 | @moduledoc """ 9 | Checks all archives are available. 10 | 11 | Mix projects can specify required archives using 12 | the `:archives` option: 13 | 14 | archives: [{:foo, "~> 1.0.0"}] 15 | 16 | This task guarantees this option is respected. 17 | """ 18 | 19 | @impl true 20 | def run(_) do 21 | archives = Mix.Project.config()[:archives] || [] 22 | 23 | Enum.each(archives, fn tuple -> 24 | {archive, req} = parse_archive(tuple) 25 | _ = Application.load(archive) 26 | vsn = Application.spec(archive, :vsn) 27 | 28 | cond do 29 | is_nil(vsn) -> 30 | Mix.raise( 31 | "Archive \"#{archive}\" could not be found. " <> 32 | "Please make sure the archive is installed locally." 33 | ) 34 | 35 | not Version.match?(List.to_string(vsn), req) -> 36 | Mix.raise( 37 | "Archive \"#{archive}-#{vsn}\" does not match requirement #{req}. " <> 38 | "Please update your archive version accordingly." 39 | ) 40 | 41 | true -> 42 | :ok 43 | end 44 | end) 45 | end 46 | 47 | defp parse_archive({archive, req}) when is_atom(archive) and is_binary(req) do 48 | case Version.parse_requirement(req) do 49 | {:ok, req} -> 50 | {archive, req} 51 | 52 | :error -> 53 | Mix.raise("Invalid requirement #{req} for archive \"#{archive}\"") 54 | end 55 | end 56 | 57 | defp parse_archive(other) do 58 | Mix.raise(""" 59 | Expected archive to be in the format: 60 | 61 | {app :: atom, requirement :: binary} 62 | 63 | got: 64 | 65 | #{inspect(other)} 66 | 67 | """) 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/archive.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Archive do 6 | use Mix.Task 7 | 8 | @shortdoc "Lists installed archives" 9 | 10 | @moduledoc """ 11 | Lists all installed archives. 12 | 13 | Archives are typically installed at `~/.mix/archives` 14 | although the installation path can be customized by 15 | setting the `MIX_ARCHIVES` environment variable. 16 | 17 | Since archives are specific to Elixir versions, it is 18 | expected from build tools to swap the `MIX_ARCHIVES` 19 | variable to different locations based on a particular 20 | Elixir installation. 21 | """ 22 | 23 | @impl true 24 | def run(_) do 25 | Mix.path_for(:archives) 26 | |> Path.join("*") 27 | |> Path.wildcard() 28 | |> Enum.map(&Path.basename/1) 29 | |> print() 30 | end 31 | 32 | defp print([]) do 33 | Mix.shell().info("No archives currently installed.") 34 | end 35 | 36 | defp print(items) do 37 | Enum.each(items, fn item -> Mix.shell().info(["* ", item]) end) 38 | Mix.shell().info("Archives installed at: #{Mix.path_for(:archives)}") 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/archive.uninstall.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Archive.Uninstall do 6 | use Mix.Task 7 | 8 | @shortdoc "Uninstalls archives" 9 | 10 | @moduledoc """ 11 | Uninstalls local archives. 12 | 13 | $ mix archive.uninstall archive.ez 14 | 15 | ## Command line options 16 | * `--force` - forces uninstallation without a shell prompt; primarily 17 | intended for automation 18 | """ 19 | 20 | @switches [ 21 | force: :boolean 22 | ] 23 | 24 | @impl true 25 | def run(argv) do 26 | Mix.Local.Installer.uninstall(Mix.path_for(:archives), "archive", argv, @switches) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/clean.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Clean do 6 | use Mix.Task 7 | 8 | @shortdoc "Deletes generated application files" 9 | @recursive true 10 | 11 | @moduledoc """ 12 | Deletes generated application files. 13 | 14 | This command deletes all build artifacts for the current project. 15 | Dependencies' sources and build files are cleaned only if the 16 | `--deps` option is given. 17 | 18 | By default this task works across all environments, unless `--only` 19 | is given. 20 | 21 | ## Command line options 22 | 23 | * `--deps` - clean dependencies as well as the current project's files 24 | * `--only` - only clean the given environment 25 | 26 | """ 27 | 28 | @switches [deps: :boolean, only: :string] 29 | 30 | @impl true 31 | def run(args) do 32 | Mix.Project.get!() 33 | loadpaths!() 34 | 35 | {opts, _, _} = OptionParser.parse(args, switches: @switches) 36 | 37 | Mix.Project.with_build_lock(fn -> 38 | do_run(opts) 39 | end) 40 | end 41 | 42 | defp do_run(opts) do 43 | # First, we get the tasks. After that, we clean them. 44 | # This is to avoid a task cleaning a compiler module. 45 | tasks = 46 | for compiler <- Mix.Task.Compiler.compilers(), 47 | module = Mix.Task.get("compile.#{compiler}"), 48 | function_exported?(module, :clean, 0), 49 | do: module 50 | 51 | Mix.Compilers.Protocol.clean() 52 | Enum.each(tasks, & &1.clean()) 53 | 54 | build = 55 | Mix.Project.build_path() 56 | |> Path.dirname() 57 | |> Path.join("*#{opts[:only]}") 58 | 59 | if opts[:deps] do 60 | build 61 | |> Path.wildcard() 62 | |> Enum.each(&File.rm_rf/1) 63 | else 64 | build 65 | |> Path.join("lib/#{Mix.Project.config()[:app]}") 66 | |> Path.wildcard() 67 | |> Enum.each(&File.rm_rf/1) 68 | end 69 | end 70 | 71 | # Loadpaths without checks because compilers may be defined in deps. 72 | defp loadpaths! do 73 | options = [ 74 | "--no-elixir-version-check", 75 | "--no-deps-check", 76 | "--no-archives-check", 77 | "--no-listeners" 78 | ] 79 | 80 | Mix.Task.run("loadpaths", options) 81 | Mix.Task.reenable("loadpaths") 82 | Mix.Task.reenable("deps.loadpaths") 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/cmd.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Cmd do 6 | use Mix.Task 7 | 8 | @shortdoc "Executes the given command" 9 | @recursive true 10 | 11 | @moduledoc """ 12 | Executes the given command. 13 | 14 | For example, you can invoke an external command such as make: 15 | 16 | $ mix cmd make 17 | 18 | By passing the `--cd` flag before the command, you can also force 19 | the command to run in a specific directory: 20 | 21 | $ mix cmd --cd "third-party" make 22 | 23 | This task is also useful in umbrella applications to execute a command 24 | on each child app: 25 | 26 | $ mix cmd pwd 27 | 28 | You can limit which apps the cmd runs in by using `mix do` with the `--app` 29 | option: 30 | 31 | $ mix do --app app1 --app app2 cmd pwd 32 | 33 | The tasks aborts whenever a command exits with a non-zero status. 34 | 35 | This task is automatically re-enabled, so it can be called multiple times 36 | with different arguments. 37 | 38 | ## Command line options 39 | 40 | * `--cd` *(since v1.10.4)* - the directory to run the command in 41 | 42 | ## Orphan operating system processes 43 | 44 | Beware that the Erlang VM does not terminate child processes 45 | when it shuts down. Therefore, if you use `mix cmd` to start 46 | long running processes and then shut down the VM, it is likely 47 | that those child processes won't be terminated with the VM. 48 | 49 | A solution is to make sure the child processes listen to the 50 | standard input and terminate when standard input is closed. 51 | We discuss this topic at length in the "Orphan operating system processes" 52 | of the `Port` module documentation. 53 | """ 54 | 55 | @switches [ 56 | app: :keep, 57 | cd: :string 58 | ] 59 | 60 | @impl true 61 | def run(args) do 62 | {opts, args} = OptionParser.parse_head!(args, strict: @switches) 63 | 64 | if args == [] do 65 | Mix.raise("Expected at least one argument in mix cmd") 66 | end 67 | 68 | apps = 69 | opts 70 | |> Keyword.get_values(:app) 71 | |> Enum.map(&String.to_atom/1) 72 | 73 | if apps != [] do 74 | IO.warn("the --app in mix cmd is deprecated. Use mix do --app instead.") 75 | end 76 | 77 | if apps == [] or Mix.Project.config()[:app] in apps do 78 | cmd_opts = Keyword.take(opts, [:cd]) 79 | 80 | case Mix.shell().cmd({hd(args), tl(args)}, cmd_opts) do 81 | 0 -> :ok 82 | status -> exit(status) 83 | end 84 | end 85 | 86 | Mix.Task.reenable("cmd") 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/compile.protocols.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Compile.Protocols do 6 | @moduledoc false 7 | use Mix.Task 8 | 9 | # TODO: Deprecate me on Elixir v1.23 10 | def run(_args) do 11 | :noop 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/deps.get.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Deps.Get do 6 | use Mix.Task 7 | 8 | @shortdoc "Fetches unavailable and out of date dependencies" 9 | 10 | @moduledoc """ 11 | Fetches unavailable and out of date dependencies. 12 | 13 | ## Command line options 14 | 15 | * `--check-locked` - raises if there are pending changes to the lockfile 16 | * `--no-archives-check` - does not check archives before fetching deps 17 | * `--only` - only fetches dependencies for given environment 18 | 19 | """ 20 | 21 | @impl true 22 | def run(args) do 23 | if "--no-archives-check" not in args do 24 | Mix.Task.run("archive.check", args) 25 | end 26 | 27 | Mix.Project.get!() 28 | 29 | {opts, _, _} = 30 | OptionParser.parse(args, switches: [only: :string, target: :string, check_locked: :boolean]) 31 | 32 | Mix.Project.with_deps_lock(fn -> 33 | do_run(opts) 34 | end) 35 | end 36 | 37 | defp do_run(opts) do 38 | fetch_opts = 39 | for {switch, key} <- [only: :env, target: :target, check_locked: :check_locked], 40 | value = opts[switch], 41 | do: {key, :"#{value}"} 42 | 43 | apps = Mix.Dep.Fetcher.all(%{}, Mix.Dep.Lock.read(), fetch_opts) 44 | 45 | if apps == [] do 46 | Mix.shell().info("All dependencies have been fetched") 47 | else 48 | :ok 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/deps.precompile.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Deps.Precompile do 6 | use Mix.Task 7 | 8 | @moduledoc """ 9 | Extension point for precompiling dependencies. 10 | 11 | This is a task that can be aliased by projects 12 | that need to execute certain tasks before 13 | compiling dependencies: 14 | 15 | aliases: ["deps.precompile": ["nerves.precompile", "deps.precompile"]] 16 | 17 | """ 18 | 19 | @impl true 20 | def run(_) do 21 | :ok 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/escript.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Escript do 6 | use Mix.Task 7 | 8 | @shortdoc "Lists installed escripts" 9 | 10 | @moduledoc ~S""" 11 | Lists all installed escripts. 12 | 13 | Escripts are installed at `~/.mix/escripts`. Add that path to your `$PATH` environment variable 14 | to be able to run installed escripts from any directory. 15 | """ 16 | 17 | import Bitwise, only: [|||: 2, &&&: 2] 18 | 19 | @impl true 20 | def run(_) do 21 | escripts_path = Mix.path_for(:escripts) 22 | 23 | escripts_path 24 | |> list_dir() 25 | |> Enum.filter(fn filename -> executable?(Path.join(escripts_path, filename)) end) 26 | |> print() 27 | end 28 | 29 | defp list_dir(path) do 30 | case File.ls(path) do 31 | {:ok, list} -> list 32 | _ -> [] 33 | end 34 | end 35 | 36 | defp executable?(path) do 37 | owner_exec_bit = 0o00100 38 | group_exec_bit = 0o00010 39 | other_exec_bit = 0o00001 40 | stat = File.stat!(path) 41 | 42 | case :os.type() do 43 | {:win32, _} -> 44 | # on win32, the script itself is not executable, but the bat is 45 | File.exists?(path <> ".bat") and stat.type == :regular 46 | 47 | _ -> 48 | executable_bit = stat.mode &&& (owner_exec_bit ||| group_exec_bit ||| other_exec_bit) 49 | executable_bit != 0 and stat.type == :regular and Path.extname(path) != ".bat" 50 | end 51 | end 52 | 53 | defp print([]) do 54 | Mix.shell().info("No escripts currently installed.") 55 | end 56 | 57 | defp print(items) do 58 | Enum.each(items, fn item -> Mix.shell().info(["* ", item]) end) 59 | Mix.shell().info("Escripts installed at: #{Mix.path_for(:escripts)}") 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/escript.uninstall.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Escript.Uninstall do 6 | use Mix.Task 7 | 8 | @shortdoc "Uninstalls escripts" 9 | 10 | @moduledoc """ 11 | Uninstalls local escripts: 12 | 13 | $ mix escript.uninstall escript_name 14 | 15 | ## Command line options 16 | * `--force` - forces uninstallation without a shell prompt; primarily 17 | intended for automation 18 | """ 19 | 20 | @switches [ 21 | force: :boolean 22 | ] 23 | 24 | @impl true 25 | def run(argv) do 26 | if path = Mix.Local.Installer.uninstall(Mix.path_for(:escripts), "escript", argv, @switches) do 27 | File.rm(path <> ".bat") 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/iex.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Iex do 6 | use Mix.Task 7 | 8 | @moduledoc """ 9 | A task that simply instructs users to run `iex -S mix`. 10 | """ 11 | 12 | @impl true 13 | def run(_) do 14 | Mix.raise("To use IEx with Mix, please run \"iex -S mix\"") 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/local.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.Local do 6 | use Mix.Task 7 | 8 | @shortdoc "Lists tasks installed locally via archives" 9 | 10 | @moduledoc """ 11 | Lists tasks installed locally via archives. 12 | """ 13 | 14 | @impl true 15 | def run([]) do 16 | shell = Mix.shell() 17 | modules = Mix.Local.archives_tasks() 18 | 19 | docs = 20 | for module <- modules do 21 | {Mix.Task.task_name(module), Mix.Task.shortdoc(module)} 22 | end 23 | 24 | max = 25 | Enum.reduce(docs, 0, fn {task, _}, acc -> 26 | max(byte_size(task), acc) 27 | end) 28 | 29 | sorted = Enum.sort(docs) 30 | 31 | Enum.each(sorted, fn {task, doc} -> 32 | shell.info(format(~c"mix ~-#{max}s # ~ts", [task, doc])) 33 | end) 34 | end 35 | 36 | defp format(expression, args) do 37 | :io_lib.format(expression, args) |> IO.iodata_to_binary() 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks/will_recompile.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.Tasks.WillRecompile do 6 | use Mix.Task 7 | @moduledoc false 8 | 9 | @doc """ 10 | Annotates the current project will recompile. 11 | """ 12 | def run(_) do 13 | config = Mix.Project.config() 14 | 15 | # Slight reimplementation of `manifest_path` because we need to 16 | # get manifests for root and children in umbrella case. 17 | paths = 18 | if Mix.Project.umbrella?(config) do 19 | build = Mix.Project.build_path(config) 20 | 21 | children = 22 | Enum.map(Mix.Project.apps_paths(config), fn {app, _} -> 23 | Path.join([build, "lib", Atom.to_string(app)]) 24 | end) 25 | 26 | [build | children] 27 | else 28 | [Mix.Project.app_path(config)] 29 | end 30 | 31 | filename = Mix.ProjectStack.reset_config_mtime() 32 | 33 | for path <- paths do 34 | path = Path.join(path, ".mix") 35 | File.mkdir_p!(path) 36 | File.touch!(Path.join(path, filename)) 37 | end 38 | 39 | :ok 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/mix/lib/mix/tasks_server.ex: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.TasksServer do 6 | @moduledoc false 7 | @name __MODULE__ 8 | 9 | use Agent 10 | 11 | def start_link(_opts) do 12 | Agent.start_link( 13 | fn -> :ets.new(@name, [:public, :set, :named_table]) end, 14 | name: @name 15 | ) 16 | end 17 | 18 | def run(tuple) do 19 | :ets.insert_new(@name, {tuple}) 20 | end 21 | 22 | def put(tuple) do 23 | :ets.insert(@name, {tuple}) 24 | :ok 25 | end 26 | 27 | def get(tuple) do 28 | :ets.member(@name, tuple) 29 | end 30 | 31 | def delete_many(many) do 32 | Enum.each(many, &:ets.delete(@name, &1)) 33 | end 34 | 35 | def clear() do 36 | :ets.delete_all_objects(@name) 37 | :ok 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/mix/mix.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | defmodule Mix.MixProject do 6 | use Mix.Project 7 | 8 | def project do 9 | [ 10 | app: :mix, 11 | build_per_environment: false, 12 | version: System.version(), 13 | escript: [main_module: Mix.CLI] 14 | ] 15 | end 16 | 17 | def application do 18 | [ 19 | registered: [Mix.State, Mix.TasksServer, Mix.ProjectStack], 20 | mod: {Mix, []}, 21 | env: [colors: []] 22 | ] 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | # Remember to update Makefile "clean_residual_files" target for any modifications 6 | # made in this file. 7 | /deps_on_git_repo/ 8 | /git_rebar/ 9 | /git_repo/ 10 | /git_sparse_repo/ 11 | /archive/ebin/ 12 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/archive/invalid-archive-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/archive/invalid-archive-0.1.0.ez -------------------------------------------------------------------------------- /lib/mix/test/fixtures/archive/lib/local.sample.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.Local.Sample do 2 | use Mix.Task 3 | 4 | @shortdoc "A local install sample" 5 | @moduledoc "A local install sample" 6 | 7 | def run(_) do 8 | Mix.shell().info("sample") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/archive/priv/.dot_file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/archive/priv/.dot_file -------------------------------------------------------------------------------- /lib/mix/test/fixtures/archive/priv/not_really_an.so: -------------------------------------------------------------------------------- 1 | see 2 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_erlang/include/r.hrl: -------------------------------------------------------------------------------- 1 | -record(r, {cell=undefined}). -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_erlang/src/b.erl: -------------------------------------------------------------------------------- 1 | -module(b). 2 | -export([b/0]). 3 | 4 | -callback c() -> term(). 5 | -record(br, {cell=undefined}). 6 | 7 | b() -> #br{cell=specified}. 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_erlang/src/c.erl: -------------------------------------------------------------------------------- 1 | -module(c). 2 | -export([c/0]). 3 | 4 | -include("r.hrl"). 5 | -behaviour(b). 6 | 7 | c() -> #r{cell=specified}. 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_leex/src/test_ok.xrl: -------------------------------------------------------------------------------- 1 | Definitions. 2 | 3 | Add = (\+|-) 4 | 5 | Number = [0-9] 6 | 7 | Rules. 8 | 9 | {Add} : make_token(add_op, TokenLine, TokenChars). 10 | 11 | {Number}+ : make_token(integer, TokenLine, TokenChars, fun erlang:list_to_integer/1). 12 | 13 | Erlang code. 14 | 15 | make_token(Name, Line, Chars) when is_list(Chars) -> 16 | {token, {Name, Line, list_to_atom(Chars)}}; 17 | make_token(Name, Line, Chars) -> 18 | {token, {Name, Line, Chars}}. 19 | 20 | make_token(Name, Line, Chars, Fun) -> 21 | {token, {Name, Line, Fun(Chars)}}. 22 | 23 | endls(Chars) -> 24 | lists:filter(fun (C) -> C == $\n orelse C == $; end, Chars). 25 | 26 | is_reserved("if") -> true; 27 | is_reserved(_) -> false. 28 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_listeners/deps/reloader/lib/reloader.ex: -------------------------------------------------------------------------------- 1 | defmodule Reloader do 2 | use GenServer 3 | 4 | def start_link(_opts) do 5 | GenServer.start_link(__MODULE__, {}) 6 | end 7 | 8 | @impl true 9 | def init({}) do 10 | {:ok, {}} 11 | end 12 | 13 | @impl true 14 | def handle_info({:modules_compiled, info}, state) do 15 | %{ 16 | modules_diff: %{added: added, changed: changed, removed: removed, timestamp: _timestamp}, 17 | app: app, 18 | scm: scm, 19 | os_pid: os_pid 20 | } = info 21 | 22 | IO.write(""" 23 | Received :modules_compiled with 24 | added: #{inspect(Enum.sort(added))}, changed: #{inspect(Enum.sort(changed))}, removed: #{inspect(Enum.sort(removed))} 25 | app: #{inspect(app)} 26 | scm: #{inspect(scm)} 27 | os_pid: #{inspect(os_pid)} 28 | """) 29 | 30 | {:noreply, state} 31 | end 32 | 33 | def handle_info({:dep_compiled, info}, state) do 34 | %{ 35 | app: app, 36 | scm: scm, 37 | manager: manager, 38 | os_pid: os_pid 39 | } = info 40 | 41 | IO.write(""" 42 | Received :dep_compiled with 43 | app: #{inspect(app)} 44 | scm: #{inspect(scm)} 45 | manager: #{inspect(manager)} 46 | os_pid: #{inspect(os_pid)} 47 | """) 48 | 49 | {:noreply, state} 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_listeners/deps/reloader/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Reloader.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :reloader, 7 | version: "0.1.0" 8 | ] 9 | end 10 | 11 | def application do 12 | [ 13 | extra_applications: [:logger] 14 | ] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/compile_yecc/src/test_ok.yrl: -------------------------------------------------------------------------------- 1 | Nonterminals 2 | Elements 3 | Value 4 | IfBlock 5 | IfBraced 6 | IfExpression 7 | ElseBraced 8 | EndIfBraced. 9 | 10 | Terminals 11 | close_tag 12 | endif_keyword 13 | if_keyword 14 | else_keyword 15 | open_tag 16 | not_keyword 17 | text. 18 | 19 | Rootsymbol 20 | Elements. 21 | 22 | Value -> '$empty' : []. 23 | 24 | Elements -> '$empty' : []. 25 | Elements -> Elements text : '$1' ++ ['$2']. 26 | Elements -> Elements IfBlock : '$1' ++ ['$2']. 27 | 28 | IfBlock -> IfBraced Elements ElseBraced Elements EndIfBraced : {ifelse, '$1', '$2', '$4'}. 29 | IfBlock -> IfBraced Elements EndIfBraced : {'if', '$1', '$2'}. 30 | 31 | IfBraced -> open_tag if_keyword IfExpression close_tag : '$3'. 32 | IfExpression -> not_keyword IfExpression : {'not', '$2'}. 33 | IfExpression -> Value : '$1'. 34 | 35 | ElseBraced -> open_tag else_keyword close_tag. 36 | EndIfBraced -> open_tag endif_keyword close_tag. 37 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :my_app, :key, :value 4 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_cycle/app1/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule App1 do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :app1, 7 | version: "0.1.0", 8 | deps: [ 9 | {:app2, "0.1.0", in_umbrella: true} 10 | ] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_cycle/app2/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule App2 do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :app2, 7 | version: "0.1.0", 8 | deps: [ 9 | {:app1, "0.1.0", in_umbrella: true} 10 | ] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidapp/ebin/invalidapp.app: -------------------------------------------------------------------------------- 1 | {application, invalidsomethingelse, [ 2 | {vsn,"0.1.0"} 3 | ]}. -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/_build/dev/lib/invalidvsn/ebin/invalidvsn.app: -------------------------------------------------------------------------------- 1 | {application, invalidvsn, [ 2 | {vsn,ok} 3 | ]}. -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/_build/dev/lib/nosemver/ebin/nosemver.app: -------------------------------------------------------------------------------- 1 | {application, nosemver, [ 2 | {vsn,"0.7"} 3 | ]}. -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/_build/dev/lib/ok/ebin/ok.app: -------------------------------------------------------------------------------- 1 | {application, ok, [ 2 | {vsn,"0.1.0"} 3 | ]}. -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/custom/bad_deps_repo/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule BadDepsRepo do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :bad_deps_repo, 7 | version: "0.1.0", 8 | deps: [ 9 | {:git_repo, "0.0.0", git: MixTest.Case.fixture_path("bad_git_repo")} 10 | ] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/custom/deps_repo/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule DepsRepo do 2 | use Mix.Project 3 | 4 | def project do 5 | opts = Process.get(:custom_deps_git_repo_opts) || [] 6 | 7 | [ 8 | app: :deps_repo, 9 | version: "0.1.0", 10 | deps: [{:git_repo, "0.1.0", [git: MixTest.Case.fixture_path("git_repo")] ++ opts}] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/custom/noscm_repo/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule NoSCMRepo do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :noscm_repo, 7 | version: "0.1.0", 8 | deps: [ 9 | {:git_repo, "0.1.0"} 10 | ] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/custom/raw_repo/lib/raw_repo.ex: -------------------------------------------------------------------------------- 1 | Application.compile_env(:raw_repo, :compile_env) 2 | 3 | defmodule RawRepo do 4 | def hello do 5 | "world" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/custom/raw_repo/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule RawRepo.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | Mix.shell().info(":raw_repo env is #{Mix.env()}") 6 | [app: :raw_repo, version: "0.1.0"] 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/deps/invalidapp/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule InvalidApp.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :invalidapp, 7 | version: "1.0" 8 | ] 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/deps/invalidvsn/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/deps_status/deps/invalidvsn/.gitkeep -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/deps/nosemver/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/deps_status/deps/nosemver/.gitkeep -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/deps/ok/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Ok.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :ok, 7 | version: "0.1.0" 8 | ] 9 | end 10 | 11 | def application do 12 | [ 13 | extra_applications: [:logger] 14 | ] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/deps_status/deps/ok/priv/sample: -------------------------------------------------------------------------------- 1 | SAMPLE -------------------------------------------------------------------------------- /lib/mix/test/fixtures/escript_test/config/config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :escript_test, erl_val: "Erlang value" 4 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/escript_test/lib/escript_test.ex: -------------------------------------------------------------------------------- 1 | defmodule EscriptTest do 2 | def start do 3 | :ok = Application.start(:escript_test) 4 | end 5 | 6 | def main(["--protocol", protocol]) do 7 | IO.puts(Protocol.consolidated?(Module.concat([protocol]))) 8 | end 9 | 10 | def main(["--nesting"]) do 11 | IO.inspect(Application.get_env(:foobar, :nesting, "TEST")) 12 | end 13 | 14 | def main(["--app-paths"]) do 15 | elixir_path = Application.app_dir(:elixir) |> String.to_charlist() 16 | escript_test_path = Application.app_dir(:escript_test) |> String.to_charlist() 17 | 18 | IO.inspect({ 19 | elixir_path != escript_test_path, 20 | match?({:ok, _}, :erl_prim_loader.list_dir(elixir_path)), 21 | match?({:ok, _}, :erl_prim_loader.list_dir(escript_test_path)) 22 | }) 23 | end 24 | 25 | def main(["--list-priv", app_name]) do 26 | # Note: :erl_prim_loader usage with Escript is currently deprecated, 27 | # but we use it only in tests for convenience 28 | 29 | app = String.to_atom(app_name) 30 | :erl_prim_loader.list_dir(~c"#{:code.lib_dir(app)}/priv") |> IO.inspect() 31 | end 32 | 33 | def main(_argv) do 34 | IO.puts(Application.get_env(:foobar, :value, "TEST")) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/escript_test/priv/hello/world.txt: -------------------------------------------------------------------------------- 1 | Hello World -------------------------------------------------------------------------------- /lib/mix/test/fixtures/escript_test/src/escript_test.erl: -------------------------------------------------------------------------------- 1 | -module(escript_test). 2 | 3 | -export([start/0, main/1]). 4 | 5 | 6 | start() -> 7 | ok = application:start(escript_test). 8 | 9 | main(Args) -> 10 | io:format("~p", [Args]). 11 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/no_mixfile/lib/a.ex: -------------------------------------------------------------------------------- 1 | defmodule A do 2 | end 3 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/no_mixfile/lib/b.ex: -------------------------------------------------------------------------------- 1 | defmodule B do 2 | end 3 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/rebar3 -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_dep/rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [warnings_as_errors]}. 2 | {project_plugins, [remove_me]}. 3 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_dep/rebar.config.script: -------------------------------------------------------------------------------- 1 | CFG1 = CONFIG ++ 2 | [{'SCRIPT', SCRIPT}] ++ 3 | [{deps, [{git_rebar, "0.1..*", {git, filename:absname("../../test/fixtures/git_rebar"), main}}]}]. 4 | 5 | case {os:getenv("FILE_FROM_ENV"), os:getenv("CONTENTS_FROM_ENV")} of 6 | {false, _} -> ok; 7 | {File, Contents} -> file:write_file(File, [Contents]) 8 | end, 9 | CFG1. 10 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_dep/src/rebar_dep.app.src: -------------------------------------------------------------------------------- 1 | {application, rebar_dep, 2 | [ 3 | {vsn, "0.1.0"} 4 | ]}. 5 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_dep/src/rebar_dep.erl: -------------------------------------------------------------------------------- 1 | -module(rebar_dep). 2 | 3 | -export ([any_function/0]). 4 | 5 | any_function() -> 6 | ok. 7 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_dep_script/rebar.config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/rebar_dep_script/rebar.config -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_dep_script/rebar.config.script: -------------------------------------------------------------------------------- 1 | [{'dir', file:get_cwd()}]. 2 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/rebar_override/rebar.config.script: -------------------------------------------------------------------------------- 1 | [ 2 | {deps, [ 3 | {git_rebar, {git, filename:absname("../../test/fixtures/git_rebar")}} 4 | ]}, 5 | {overrides, [ 6 | {override, git_rebar, [{deps, [{git_repo, {git, filename:absname("../../test/fixtures/git_repo")}}]}]} 7 | ]} 8 | ]. 9 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/release_test/config/config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :release_test, :static, :was_set 4 | config :release_test, :encoding, {:_μ, :"£", "£", ~c"£"} 5 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/release_test/lib/release_test.ex: -------------------------------------------------------------------------------- 1 | defmodule ReleaseTest do 2 | use Application 3 | 4 | def start(_type, _args) do 5 | cookie = System.get_env("RELEASE_COOKIE") 6 | {:ok, [[sys_config]]} = :init.get_argument(:config) 7 | 8 | info = %{ 9 | app_dir: Application.app_dir(:release_test), 10 | cookie_env: cookie, 11 | encoding: Application.get_env(:release_test, :encoding), 12 | mode: :code.get_mode(), 13 | node: node(), 14 | protocols_consolidated?: Protocol.consolidated?(Enumerable), 15 | release_name: System.get_env("RELEASE_NAME"), 16 | release_mode: System.get_env("RELEASE_MODE"), 17 | release_node: System.get_env("RELEASE_NODE"), 18 | release_root: System.get_env("RELEASE_ROOT"), 19 | release_vsn: System.get_env("RELEASE_VSN"), 20 | release_prog: System.get_env("RELEASE_PROG"), 21 | root_dir: :code.root_dir() |> to_string(), 22 | runtime_config: Application.fetch_env(:release_test, :runtime), 23 | static_config: Application.fetch_env(:release_test, :static), 24 | sys_config_env: System.get_env("RELEASE_SYS_CONFIG"), 25 | sys_config_init: to_string(sys_config) 26 | } 27 | 28 | path = Path.join(System.get_env("RELEASE_ROOT"), "RELEASE_BOOTED") 29 | File.write!(path, :erlang.term_to_binary(info)) 30 | 31 | if System.get_env("BOOTED_ONCE") do 32 | IO.puts("RESTARTED!!!") 33 | else 34 | System.put_env("BOOTED_ONCE", "1") 35 | end 36 | 37 | if System.get_env("RELEASE_NAME") =~ "permanent" do 38 | Supervisor.start_link([], strategy: :one_for_one) 39 | else 40 | System.halt(0) 41 | end 42 | end 43 | 44 | def hello_world do 45 | IO.puts("hello world") 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/release_test/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule ReleaseTest.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :release_test, 7 | version: "0.1.0" 8 | ] 9 | end 10 | 11 | def application do 12 | [ 13 | extra_applications: [:logger, :runtime_tools], 14 | mod: {ReleaseTest, []} 15 | ] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/release_test/priv/hello: -------------------------------------------------------------------------------- 1 | world -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_failed/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule TestFailed.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :test_only_failures, 7 | version: "0.0.1", 8 | test_load_filters: [~r/.*_test_failed\.exs/] 9 | ] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_failed/test/only_failing_test_failed.exs: -------------------------------------------------------------------------------- 1 | defmodule OnlyFailingTest do 2 | use ExUnit.Case 3 | 4 | test "fails", do: assert(System.get_env("PASS_FAILING_TESTS")) 5 | end 6 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_failed/test/only_passing_test_failed.exs: -------------------------------------------------------------------------------- 1 | IO.puts("loading OnlyPassingTest") 2 | 3 | defmodule OnlyPassingTest do 4 | use ExUnit.Case 5 | 6 | test "passes", do: assert(1 == 1) 7 | end 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_failed/test/passing_and_failing_test_failed.exs: -------------------------------------------------------------------------------- 1 | defmodule PassingAndFailingTest do 2 | use ExUnit.Case 3 | 4 | @tag :foo 5 | test "fails", do: assert(System.get_env("PASS_FAILING_TESTS")) 6 | 7 | @tag :foo 8 | test "passes", do: assert(1 == 1) 9 | end 10 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_failed/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_stale/lib/a.ex: -------------------------------------------------------------------------------- 1 | defmodule A do 2 | def f, do: :ok 3 | end 4 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_stale/lib/b.ex: -------------------------------------------------------------------------------- 1 | defmodule B do 2 | def f, do: A.f() 3 | end 4 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_stale/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule TestStale.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :test_stale, 7 | version: "0.0.1", 8 | test_load_filters: [fn file -> String.ends_with?(file, "_test_stale.exs") end] 9 | ] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_stale/test/a_test_stale.exs: -------------------------------------------------------------------------------- 1 | defmodule ATest do 2 | use ExUnit.Case 3 | 4 | test "f" do 5 | assert A.f() == :ok 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_stale/test/b_test_stale.exs: -------------------------------------------------------------------------------- 1 | defmodule BTest do 2 | use ExUnit.Case 3 | 4 | test "f" do 5 | assert B.f() == :ok 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/test_stale/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/bar/lib/bar.ex: -------------------------------------------------------------------------------- 1 | defmodule Bar do 2 | def bar do 3 | "hello world" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/bar/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Bar.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | Mix.shell().info(":bar env is #{Mix.env()}") 6 | 7 | [ 8 | app: :bar, 9 | version: "0.1.0", 10 | deps: [{:foo, in_umbrella: true}] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/dont_error_on_files: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/dont_error_on_files -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/dont_error_on_missing_mixfile/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elixir-lang/elixir/85e068e144b09a27d08ee3fb7c53f154263e967c/lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/dont_error_on_missing_mixfile/.gitkeep -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/foo/lib/foo.ex: -------------------------------------------------------------------------------- 1 | defmodule Foo do 2 | def foo do 3 | "bye world" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/apps/foo/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Foo.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | Mix.shell().info(":foo env is #{Mix.env()}") 6 | 7 | [ 8 | app: :foo, 9 | version: "0.1.0" 10 | ] 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/deps/umbrella/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Umbrella.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [apps_path: "apps"] 6 | end 7 | 8 | def application do 9 | [extra_applications: [:runtime_tools]] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_dep/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule UmbrellaDep.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :umbrella_dep, 7 | version: "0.1.0", 8 | deps: deps() 9 | ] 10 | end 11 | 12 | defp deps do 13 | [ 14 | {:umbrella, path: "deps/umbrella"} 15 | ] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/bar/lib/bar.ex: -------------------------------------------------------------------------------- 1 | defmodule Bar do 2 | def hello do 3 | :world 4 | end 5 | end 6 | 7 | defmodule Bar.Ignore do 8 | def world do 9 | :hello 10 | end 11 | end 12 | 13 | defprotocol Bar.Protocol do 14 | def to_uppercase(string) 15 | end 16 | 17 | defimpl Bar.Protocol, for: BitString do 18 | def to_uppercase(string), do: String.upcase(string) 19 | end 20 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/bar/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Bar.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :bar, 7 | version: "0.1.0", 8 | # Choose something besides *_test.exs so that these test files don't 9 | # get accidentally swept up into the actual Mix test suite. 10 | test_load_filters: [~r/.*_tests\.exs/], 11 | test_coverage: [ignore_modules: [Bar, ~r/Ignore/]], 12 | aliases: [mytask: fn _ -> Mix.shell().info("bar_running") end] 13 | ] 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/bar/test/bar_tests.exs: -------------------------------------------------------------------------------- 1 | defmodule BarTest do 2 | use ExUnit.Case 3 | 4 | test "greets the world" do 5 | assert Bar.hello() == :world 6 | end 7 | 8 | test "world the greets" do 9 | assert Bar.Ignore.world() == :hello 10 | end 11 | 12 | @tag :maybe_skip 13 | test "works with protocols" do 14 | assert Bar.Protocol.to_uppercase("foo") == "FOO" 15 | end 16 | 17 | test "protocols are consolidated" do 18 | assert Protocol.consolidated?(Bar.Protocol) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/bar/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/foo/lib/foo.ex: -------------------------------------------------------------------------------- 1 | defmodule Foo do 2 | def hello do 3 | :world 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/foo/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Foo.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :foo, 7 | version: "0.1.0", 8 | # Choose something besides *_test.exs so that these test files don't 9 | # get accidentally swept up into the actual Mix test suite. 10 | test_load_filters: [~r/.*_tests\.exs/], 11 | aliases: [mytask: fn _ -> Mix.shell().info("foo_running") end] 12 | ] 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/foo/test/foo_tests.exs: -------------------------------------------------------------------------------- 1 | defmodule FooTest do 2 | use ExUnit.Case 3 | 4 | test "greets the world" do 5 | assert Foo.hello() == :world 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/apps/foo/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /lib/mix/test/fixtures/umbrella_test/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule UmbrellaTest.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | apps_path: "apps" 7 | ] 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/mix/test/mix/aliases_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.AliasesTest do 8 | use MixTest.Case 9 | 10 | defmodule Aliases do 11 | def project do 12 | [ 13 | aliases: [ 14 | h: "hello", 15 | p: &inspect/1, 16 | compile: "hello", 17 | cmd: &call_cmd/1, 18 | help: ["help", "hello"], 19 | "nested.h": [&Mix.shell().info(inspect(&1)), "h foo bar"], 20 | invalid_alias: [:not_a_string_or_function] 21 | ] 22 | ] 23 | end 24 | 25 | defp call_cmd(args), do: Mix.Task.run("cmd", args) 26 | end 27 | 28 | setup do 29 | Mix.Project.push(Aliases) 30 | :ok 31 | end 32 | 33 | test "runs string aliases" do 34 | assert Mix.Task.run("h", []) == "Hello, World!" 35 | assert Mix.Task.run("h", []) == :noop 36 | assert Mix.Task.run("hello", []) == :noop 37 | 38 | Mix.Task.reenable("h") 39 | Mix.Task.reenable("hello") 40 | assert Mix.Task.run("h", ["foo", "bar"]) == "Hello, foo bar!" 41 | end 42 | 43 | test "runs function aliases" do 44 | assert Mix.Task.run("p", []) == "[]" 45 | assert Mix.Task.run("p", []) == :noop 46 | 47 | Mix.Task.reenable("p") 48 | assert Mix.Task.run("p", ["foo", "bar"]) == "[\"foo\", \"bar\"]" 49 | end 50 | 51 | test "runs list aliases" do 52 | assert Mix.Task.run("nested.h", ["baz"]) == "Hello, foo bar baz!" 53 | assert_received {:mix_shell, :info, ["[]"]} 54 | end 55 | 56 | test "fails for invalid aliases" do 57 | assert_raise Mix.Error, ~r/Invalid Mix alias format/, fn -> 58 | Mix.Task.run("invalid_alias", []) 59 | end 60 | end 61 | 62 | test "run alias override" do 63 | assert Mix.Task.run("compile", []) == "Hello, World!" 64 | assert Mix.Task.run("compile", []) == :noop 65 | end 66 | 67 | test "run alias override with name-recursion" do 68 | assert Mix.Task.rerun("help", []) == "Hello, World!" 69 | assert_received {:mix_shell, :info, ["mix test" <> _]} 70 | 71 | # Arguments are passed to the recursive task and not the last one. 72 | assert ExUnit.CaptureIO.capture_io(fn -> 73 | Mix.Task.rerun("help", ["test"]) 74 | end) =~ "mix test" 75 | end 76 | 77 | test "run alias override with code-recursion" do 78 | assert Mix.Task.rerun("cmd", ["echo", "hello"]) == :ok 79 | assert_received {:mix_shell, :run, ["hello" <> _]} 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/mix/test/mix/dep/converger_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | Code.require_file("../../test_helper.exs", __DIR__) 5 | 6 | defmodule Mix.Dep.ConvergerTest do 7 | use MixTest.Case 8 | 9 | describe "topological_sort" do 10 | test "raises if there is a cycle in the dependency graph" do 11 | app1 = %Mix.Dep{app: :app1} 12 | app2 = %Mix.Dep{app: :app2} 13 | app3 = %Mix.Dep{app: :app3} 14 | 15 | deps = [ 16 | # not really part of the cycle, just depend on it 17 | %Mix.Dep{app: :app5, deps: [app1, app3]}, 18 | %Mix.Dep{app: :app4, deps: [app2]}, 19 | 20 | # cycle 21 | %{app1 | deps: [app2]}, 22 | %{app2 | deps: [app3]}, 23 | %{app3 | deps: [app1]} 24 | ] 25 | 26 | assert_raise Mix.Error, 27 | "Could not sort dependencies. " <> 28 | "The following dependencies form a cycle: app1, app2, app3", 29 | fn -> Mix.Dep.Converger.topological_sort(deps) end 30 | end 31 | 32 | test "raises if an app depends upon itself" do 33 | app = %Mix.Dep{app: :self_dependent} 34 | deps = [%{app | deps: [app]}] 35 | 36 | assert_raise Mix.Error, 37 | "App self_dependent lists itself as a dependency", 38 | fn -> Mix.Dep.Converger.topological_sort(deps) end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/mix/test/mix/dep/lock_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Dep.LockTest do 8 | use MixTest.Case 9 | 10 | setup do 11 | Mix.Project.push(MixTest.Case.Sample) 12 | :ok 13 | end 14 | 15 | test "creates new lock and manifest files", context do 16 | in_tmp(context.test, fn -> 17 | Mix.Dep.Lock.write(%{foo: :bar}) 18 | assert File.regular?("mix.lock") 19 | assert File.regular?("_build/dev/lib/sample/.mix/compile.lock") 20 | end) 21 | end 22 | 23 | test "formats each dep on its own line for better conflict handling", context do 24 | in_tmp(context.test, fn -> 25 | Mix.Dep.Lock.write(%{ 26 | foo: {:hex, :foo, "0.1.0"}, 27 | bar: {:hex, :bar, "0.1.0"} 28 | }) 29 | 30 | assert File.read!("mix.lock") == ~S""" 31 | %{ 32 | "bar": {:hex, :bar, "0.1.0"}, 33 | "foo": {:hex, :foo, "0.1.0"}, 34 | } 35 | """ 36 | end) 37 | end 38 | 39 | test "does not touch manifest file there is no change", context do 40 | in_tmp(context.test, fn -> 41 | Mix.Dep.Lock.write(%{foo: :bar, bar: :bat}) 42 | File.rm!("_build/dev/lib/sample/.mix/compile.lock") 43 | 44 | Mix.Dep.Lock.write(%{bar: :bat, foo: :bar}) 45 | refute File.regular?("_build/dev/lib/sample/.mix/compile.lock") 46 | end) 47 | end 48 | 49 | test "raises a proper error if check_locked opt is true and there are changes", context do 50 | in_tmp(context.test, fn -> 51 | Mix.Dep.Lock.write(%{foo: :bar}) 52 | 53 | Mix.Dep.Lock.write(%{foo: :bar}, check_locked: true) 54 | 55 | assert_raise Mix.Error, 56 | ~r/Your mix\.lock is out of date and must be updated without the --check-locked flag/, 57 | fn -> 58 | Mix.Dep.Lock.write(%{foo: :bar, bar: :bat}, check_locked: true) 59 | end 60 | end) 61 | end 62 | 63 | test "raises a proper error for merge conflicts", context do 64 | in_tmp(context.test, fn -> 65 | File.write("mix.lock", ~S""" 66 | %{ 67 | "dep": {:hex, :dep, "0.1.0"}, 68 | <<<<<<< HEAD 69 | "foo": {:hex, :foo, "0.1.0"}, 70 | ======= 71 | "bar": {:hex, :bar, "0.1.0"}, 72 | >>>>>>> foobar 73 | "baz": {:hex, :baz, "0.1.0"}, 74 | } 75 | """) 76 | 77 | assert_raise Mix.Error, ~r/Your mix\.lock contains merge conflicts/, fn -> 78 | Mix.Dep.Lock.read() 79 | end 80 | end) 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /lib/mix/test/mix/local_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.LocalTest do 8 | use MixTest.Case 9 | 10 | @csv """ 11 | 1.2.5,ABC,0.9.0,26 12 | 1.2.3,DEF,1.0.0,26 13 | 1.2.4,GHI,1.0.0,26 14 | """ 15 | 16 | @tag :tmp_dir 17 | test "select correct versions from csv", %{tmp_dir: tmp_dir} do 18 | File.cd!(tmp_dir, fn -> 19 | File.write!("csv", @csv) 20 | 21 | assert {"1.0.0", "1.2.4", "GHI", "26"} = 22 | Mix.Local.find_matching_versions!("name", nil, "csv") 23 | end) 24 | end 25 | 26 | @tag :tmp_dir 27 | test "select specific version from csv", %{tmp_dir: tmp_dir} do 28 | File.cd!(tmp_dir, fn -> 29 | File.write!("csv", @csv) 30 | 31 | assert {"0.9.0", "1.2.5", "ABC", "26"} = 32 | Mix.Local.find_matching_versions!("name", "1.2.5", "csv") 33 | 34 | assert {"1.0.0", "1.2.3", "DEF", "26"} = 35 | Mix.Local.find_matching_versions!("name", "1.2.3", "csv") 36 | 37 | assert_raise Mix.Error, "Could not find a version of name matching: 1.3.0", fn -> 38 | Mix.Local.find_matching_versions!("name", "1.3.0", "csv") 39 | end 40 | end) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/mix/test/mix/scm_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.SCMTest do 8 | use MixTest.Case 9 | 10 | setup do 11 | available = Mix.SCM.available() 12 | on_exit(fn -> Mix.State.put(:scm, available) end) 13 | :ok 14 | end 15 | 16 | test "prepends an SCM" do 17 | Mix.SCM.prepend(Hello) 18 | assert Enum.at(Mix.SCM.available(), 0) == Hello 19 | Mix.SCM.delete(Hello) 20 | assert Hello not in Mix.SCM.available() 21 | end 22 | 23 | test "appends an SCM" do 24 | Mix.SCM.append(Hello) 25 | assert Enum.at(Mix.SCM.available(), -1) == Hello 26 | Mix.SCM.delete(Hello) 27 | assert Hello not in Mix.SCM.available() 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/mix/test/mix/shell/quiet_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Shell.QuietTest do 8 | use MixTest.Case 9 | 10 | import ExUnit.CaptureIO 11 | import Mix.Shell.Quiet 12 | 13 | test "prints nothing to stdio when info is invoked" do 14 | assert capture_io(fn -> info("hello") end) == "" 15 | end 16 | 17 | test "prints error message to stderr" do 18 | assert capture_io(:stderr, fn -> error("hello") end) =~ "hello" 19 | end 20 | 21 | test "asks the user with yes?" do 22 | assert capture_io("\n", fn -> yes?("Ok?") end) == "Ok? [Yn] " 23 | assert capture_io("\n", fn -> assert yes?("Ok?") end) 24 | assert capture_io("Yes", fn -> assert yes?("Ok?") end) 25 | assert capture_io("yes", fn -> assert yes?("Ok?") end) 26 | assert capture_io("y", fn -> assert yes?("Ok?") end) 27 | 28 | assert capture_io("n", fn -> refute yes?("Ok?") end) 29 | assert capture_io("", fn -> refute yes?("Ok?") end) 30 | end 31 | 32 | test "runs a given command" do 33 | assert capture_io("", fn -> assert cmd("echo hello") == 0 end) == "" 34 | 35 | wont_print_sample() 36 | assert capture_io("", fn -> assert cmd("echo hello", print_app: false) == 0 end) == "" 37 | assert capture_io("", fn -> assert cmd("echo hello") == 0 end) == "" 38 | end 39 | 40 | defp wont_print_sample do 41 | Mix.Project.push(nil) 42 | Mix.Project.push(MixTest.Case.Sample) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/mix/test/mix/shell_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.ShellTest do 8 | use MixTest.Case 9 | 10 | defp capture_io(fun) do 11 | fun |> ExUnit.CaptureIO.capture_io() |> String.replace("\r\n", "\n") 12 | end 13 | 14 | test "executes cmd with expressions" do 15 | Mix.shell(Mix.Shell.IO) 16 | 17 | assert capture_io(fn -> 18 | assert Mix.shell().cmd("echo first && echo second") == 0 19 | end) 20 | |> String.replace(" \n", "\n") == "first\nsecond\n" 21 | after 22 | Mix.shell(Mix.Shell.Process) 23 | end 24 | 25 | test "with :cd" do 26 | Mix.shell(Mix.Shell.IO) 27 | tmp_dir = System.tmp_dir() 28 | File.mkdir_p!(tmp_dir) 29 | {pwd, 0} = System.cmd("pwd", [], cd: tmp_dir) 30 | 31 | assert ExUnit.CaptureIO.capture_io(fn -> 32 | Mix.shell().cmd("pwd", cd: tmp_dir) 33 | end) == pwd 34 | after 35 | Mix.shell(Mix.Shell.Process) 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/clean_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.CleanTest do 8 | use MixTest.Case 9 | 10 | defmodule Sample do 11 | def project do 12 | [ 13 | app: :sample, 14 | version: "0.1.0", 15 | deps: [ 16 | {:ok, "0.1.0", path: "deps/ok"}, 17 | {:unknown, "0.1.0", git: "deps/unknown"} 18 | ] 19 | ] 20 | end 21 | end 22 | 23 | test "cleans the application build" do 24 | in_fixture("deps_status", fn -> 25 | Mix.Project.push(Sample) 26 | 27 | File.mkdir_p!("_build/dev/lib/sample/consolidated") 28 | File.mkdir_p!("_build/dev/lib/sample") 29 | File.mkdir_p!("_build/test/lib/sample") 30 | File.mkdir_p!("_build/dev/lib/ok") 31 | 32 | Mix.Tasks.Clean.run([]) 33 | refute File.exists?("_build/dev/lib/sample/consolidated") 34 | refute File.exists?("_build/dev/lib/sample") 35 | refute File.exists?("_build/test/lib/sample") 36 | assert File.exists?("_build/dev/lib/ok") 37 | end) 38 | end 39 | 40 | test "cleans dependencies build" do 41 | in_fixture("deps_status", fn -> 42 | Mix.Project.push(Sample) 43 | 44 | File.mkdir_p!("_build/dev/lib/ok") 45 | File.mkdir_p!("_build/test/lib/ok") 46 | 47 | Mix.Tasks.Clean.run(["--deps", "--only", "dev"]) 48 | refute File.exists?("_build/dev") 49 | assert File.exists?("_build/test") 50 | 51 | Mix.Tasks.Clean.run(["--deps"]) 52 | refute File.exists?("_build/test") 53 | end) 54 | end 55 | 56 | test "invokes compiler hook defined in project" do 57 | Mix.ProjectStack.post_config(compilers: Mix.compilers() ++ [:testc]) 58 | 59 | in_fixture("no_mixfile", fn -> 60 | Mix.Project.push(MixTest.Case.Sample) 61 | 62 | File.write!("lib/testc.ex", """ 63 | defmodule Mix.Tasks.Compile.Testc do 64 | use Mix.Task.Compiler 65 | 66 | @impl true 67 | def run(_args) do 68 | Mix.shell().info("Compiling...") 69 | :ok 70 | end 71 | 72 | @impl true 73 | def clean do 74 | Mix.shell().info("Cleaning...") 75 | :ok 76 | end 77 | end 78 | """) 79 | 80 | Mix.Task.run("compile") 81 | assert_received {:mix_shell, :info, ["Compiling..."]} 82 | purge([Mix.Tasks.Compile.Testc]) 83 | 84 | Mix.Task.run("clean") 85 | assert_received {:mix_shell, :info, ["Cleaning..."]} 86 | end) 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/compile.leex_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.Compile.LeexTest do 8 | use MixTest.Case 9 | import ExUnit.CaptureIO 10 | 11 | setup do 12 | Mix.ProjectStack.post_config(compilers: [:leex | Mix.compilers()]) 13 | Mix.Project.push(MixTest.Case.Sample) 14 | :ok 15 | end 16 | 17 | test "compilation continues if one file fails to compile" do 18 | in_fixture("compile_leex", fn -> 19 | file = Path.absname("src/zzz.xrl") 20 | 21 | File.write!(file, """ 22 | oops. 23 | """) 24 | 25 | capture_io(fn -> 26 | assert {:error, [diagnostic]} = Mix.Tasks.Compile.Leex.run(["--force"]) 27 | 28 | assert %Mix.Task.Compiler.Diagnostic{ 29 | compiler_name: "leex", 30 | file: ^file, 31 | source: ^file, 32 | message: "missing Definitions", 33 | position: 1, 34 | severity: :error 35 | } = diagnostic 36 | end) 37 | 38 | assert File.regular?("src/test_ok.erl") 39 | end) 40 | end 41 | 42 | test "compiles src/test_ok.xrl" do 43 | in_fixture("compile_leex", fn -> 44 | assert Mix.Tasks.Compile.Leex.run(["--verbose"]) == {:ok, []} 45 | assert_received {:mix_shell, :info, ["Compiled src/test_ok.xrl"]} 46 | assert File.regular?("src/test_ok.erl") 47 | 48 | assert Mix.Tasks.Compile.Leex.run(["--verbose"]) == {:noop, []} 49 | refute_received {:mix_shell, :info, ["Compiled src/test_ok.xrl"]} 50 | 51 | assert Mix.Tasks.Compile.Leex.run(["--force", "--verbose"]) == {:ok, []} 52 | assert_received {:mix_shell, :info, ["Compiled src/test_ok.xrl"]} 53 | end) 54 | end 55 | 56 | test "removes old artifact files" do 57 | in_fixture("compile_leex", fn -> 58 | assert Mix.Tasks.Compile.Leex.run([]) == {:ok, []} 59 | assert File.regular?("src/test_ok.erl") 60 | 61 | File.rm!("src/test_ok.xrl") 62 | assert Mix.Tasks.Compile.Leex.run([]) == {:ok, []} 63 | refute File.regular?("src/test_ok.erl") 64 | end) 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/deps.path_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.DepsPathTest do 8 | use MixTest.Case 9 | 10 | defmodule DepsApp do 11 | def project do 12 | [ 13 | app: :raw_sample, 14 | version: "0.1.0", 15 | deps: [ 16 | {:raw_repo, "0.1.0", path: "custom/raw_repo"} 17 | ] 18 | ] 19 | end 20 | end 21 | 22 | defmodule MismatchDepsApp do 23 | def project do 24 | [ 25 | app: :raw_sample, 26 | version: "0.1.0", 27 | deps: [ 28 | {:cooked_repo, "0.1.0", path: "custom/raw_repo"} 29 | ] 30 | ] 31 | end 32 | end 33 | 34 | @tag apps: [:raw_sample] 35 | test "compiles and runs even if lock does not match" do 36 | in_fixture("deps_status", fn -> 37 | Mix.Project.push(DepsApp) 38 | 39 | Mix.Dep.Lock.write(%{raw_repo: "abcdef"}) 40 | Mix.Tasks.Run.run(["-e", "Mix.shell().info RawRepo.hello()"]) 41 | assert_received {:mix_shell, :info, ["==> raw_repo"]} 42 | assert_received {:mix_shell, :info, ["world"]} 43 | end) 44 | end 45 | 46 | @tag apps: [:raw_sample] 47 | test "uses the name of the app, not the path basename" do 48 | in_fixture("deps_status", fn -> 49 | Mix.Project.push(MismatchDepsApp) 50 | 51 | Mix.Tasks.Deps.Compile.run([]) 52 | assert File.exists?("_build/dev/lib/cooked_repo/ebin") 53 | end) 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/eval_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | 4 | Code.require_file("../../test_helper.exs", __DIR__) 5 | 6 | defmodule Mix.Tasks.EvalTest do 7 | use MixTest.Case 8 | 9 | setup do 10 | Mix.Project.push(MixTest.Case.Sample) 11 | end 12 | 13 | test "does not start applications", context do 14 | in_tmp(context.test, fn -> 15 | expr = "send self(), {:apps, Application.started_applications()}" 16 | Mix.Tasks.Eval.run([expr]) 17 | assert_received {:apps, apps} 18 | refute List.keyfind(apps, :sample, 0) 19 | end) 20 | end 21 | 22 | test "runs multiple commands", context do 23 | in_tmp(context.test, fn -> 24 | Mix.Tasks.Eval.run(["send self(), {:eval, :foo}"]) 25 | assert_received {:eval, :foo} 26 | 27 | Mix.Tasks.Eval.run(["send self(), {:eval, :bar}"]) 28 | assert_received {:eval, :bar} 29 | end) 30 | end 31 | 32 | test "accepts arguments", context do 33 | in_tmp(context.test, fn -> 34 | Mix.Tasks.Eval.run(["send self(), {:argv, System.argv()}", "bar", "baz"]) 35 | assert_received {:argv, ~w[bar baz]} 36 | end) 37 | end 38 | 39 | test "resets argv to previous value", context do 40 | argv = System.argv() 41 | 42 | try do 43 | in_tmp(context.test, fn -> 44 | System.argv(["foo"]) 45 | 46 | Mix.Tasks.Eval.run(["send self(), {:argv, System.argv()}", "bar", "baz"]) 47 | assert_received {:argv, ~w[bar baz]} 48 | 49 | assert ["foo"] == System.argv() 50 | end) 51 | after 52 | System.argv(argv) 53 | end 54 | end 55 | 56 | test "runs without mix.exs" do 57 | Mix.Project.pop() 58 | 59 | assert_raise Mix.Error, ~r/Cannot execute "mix eval" without a Mix.Project/, fn -> 60 | Mix.Tasks.Eval.run(["send self(), {:eval, :foo}"]) 61 | end 62 | 63 | Mix.Tasks.Eval.run(["--no-mix-exs", "send self(), {:eval, :foo}"]) 64 | assert_received {:eval, :foo} 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/iex_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.IExTest do 8 | use MixTest.Case, async: true 9 | 10 | test "raises error message about correct usage", context do 11 | in_tmp(context.test, fn -> 12 | msg = "To use IEx with Mix, please run \"iex -S mix\"" 13 | 14 | assert_raise Mix.Error, msg, fn -> 15 | Mix.Tasks.Iex.run([]) 16 | end 17 | end) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/local_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.LocalTest do 8 | use MixTest.Case 9 | 10 | test "MIX_PATH" do 11 | File.rm_rf!(tmp_path("mixpath")) 12 | System.put_env("MIX_PATH", tmp_path("mixpath/ebin")) 13 | 14 | File.mkdir_p!(tmp_path("mixpath/ebin")) 15 | Mix.Local.append_paths() 16 | 17 | # Install on MIX_PATH manually 18 | File.copy!( 19 | fixture_path("archive/ebin/Elixir.Mix.Tasks.Local.Sample.beam"), 20 | tmp_path("mixpath/ebin/Elixir.Mix.Tasks.Local.Sample.beam") 21 | ) 22 | 23 | # Run it 24 | Mix.Task.run("local.sample") 25 | assert_received {:mix_shell, :info, ["sample"]} 26 | after 27 | purge([Mix.Tasks.Local.Sample]) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/release.init_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.Release.InitTest do 8 | use MixTest.Case 9 | 10 | test "copies templates as is" do 11 | in_tmp("release_init", fn -> 12 | Mix.Task.run("release.init", []) 13 | assert_received {:mix_shell, :info, ["* creating rel/vm.args.eex"]} 14 | assert_received {:mix_shell, :info, ["* creating rel/remote.vm.args.eex"]} 15 | assert_received {:mix_shell, :info, ["* creating rel/env.sh.eex"]} 16 | assert_received {:mix_shell, :info, ["* creating rel/env.bat.eex"]} 17 | 18 | assert File.exists?("rel/vm.args.eex") 19 | assert File.exists?("rel/remote.vm.args.eex") 20 | assert File.exists?("rel/env.sh.eex") 21 | assert File.exists?("rel/env.bat.eex") 22 | end) 23 | end 24 | 25 | test "can be set to --force and --quiet" do 26 | in_tmp("release_init", fn -> 27 | Mix.Task.run("release.init", ["--force", "--quiet"]) 28 | Mix.Task.run("release.init", ["--force", "--quiet"]) 29 | refute_received {:mix_shell, :info, ["* creating rel/vm.args.eex"]} 30 | refute_received {:mix_shell, :info, ["* creating rel/remote.vm.args.eex"]} 31 | refute_received {:mix_shell, :info, ["* creating rel/env.sh.eex"]} 32 | refute_received {:mix_shell, :info, ["* creating rel/env.bat.eex"]} 33 | end) 34 | end 35 | 36 | test "raises on bad input" do 37 | assert_raise OptionParser.ParseError, 38 | ~r"--unknown : Unknown option", 39 | fn -> Mix.Tasks.Release.Init.run(["--unknown"]) end 40 | 41 | assert_raise Mix.Error, 42 | ~r/Expected "mix release.init" without arguments, got: \["foo", "bar"\]/, 43 | fn -> Mix.Tasks.Release.Init.run(["foo", "bar"]) end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/mix/test/mix/tasks/will_recompile_test.exs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team 3 | # SPDX-FileCopyrightText: 2012 Plataformatec 4 | 5 | Code.require_file("../../test_helper.exs", __DIR__) 6 | 7 | defmodule Mix.Tasks.WillRecompileTest do 8 | use MixTest.Case 9 | 10 | test "marks current project to recompile" do 11 | in_fixture("deps_status/deps/ok", fn -> 12 | Mix.Project.in_project(:ok, ".", fn _ -> 13 | refute File.exists?("_build/dev/lib/ok/.mix/compile.lock") 14 | Mix.Task.run("will_recompile") 15 | assert File.exists?("_build/dev/lib/ok/.mix/compile.lock") 16 | end) 17 | end) 18 | end 19 | 20 | test "marks all projects in umbrella to recompile including the root itself" do 21 | in_fixture("umbrella_dep/deps/umbrella", fn -> 22 | Mix.Project.in_project(:umbrella, ".", fn _ -> 23 | refute File.exists?("_build/dev/.mix/compile.lock") 24 | refute File.exists?("_build/dev/lib/foo/.mix/compile.lock") 25 | refute File.exists?("_build/dev/lib/bar/.mix/compile.lock") 26 | Mix.Task.run("will_recompile") 27 | assert File.exists?("_build/dev/.mix/compile.lock") 28 | assert File.exists?("_build/dev/lib/foo/.mix/compile.lock") 29 | assert File.exists?("_build/dev/lib/bar/.mix/compile.lock") 30 | end) 31 | end) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /man/elixir.1.in: -------------------------------------------------------------------------------- 1 | .\" SPDX-License-Identifier: Apache-2.0 2 | .\" SPDX-FileCopyrightText: 2021 The Elixir Team 3 | .\" SPDX-FileCopyrightText: 2012 Plataformatec 4 | .Dd February 3, 2019 5 | .Dt ELIXIR 1 6 | .Os 7 | .Sh NAME 8 | .Nm elixir 9 | .Nd The Elixir script runner 10 | .Sh SYNOPSIS 11 | .Nm 12 | .Op Ar OPTIONS 13 | .Ar 14 | .Sh DESCRIPTION 15 | The program starts the runtime system typically for the execution of one or more scripts. It is similar to 16 | .Xr iex 1 , 17 | but 18 | .Nm 19 | exits when the executed script does. 20 | .Sh OPTIONS 21 | Note that many of the options mentioned here were borrowed from the Erlang shell, therefore 22 | .Xr erl 1 23 | can be used as an additional source of information on the options. 24 | .Bl -tag -width Ds 25 | {COMMON} 26 | .It Fl -no-halt 27 | Does not halt the Erlang VM after execution. 28 | .It Fl - 29 | Separates the options passed to the compiler from the options passed to the executed code. 30 | .El 31 | .Sh NOTES 32 | The following options can be given more than once: 33 | .Fl -boot-var Ns , Fl -erl-config Ns , Fl -eval Ns , Fl -rpc-eval Ns . 34 | .Sh ENVIRONMENT 35 | .Bl -tag -width Ds 36 | .It Ev ELIXIR_ERL_OPTIONS 37 | Allows passing parameters to the Erlang runtime. 38 | .El 39 | .Sh FILES 40 | .Bl -tag -width Ds 41 | .It Pa ~/.erlang.cookie 42 | Stores the magic cookie value which is used only when it wasn't specified via the option 43 | .Fl -cookie 44 | .Pq see above . 45 | If the file doesn't exist when a node starts, it will be created. 46 | .El 47 | .Sh SEE ALSO 48 | .Xr elixirc 1 , 49 | .Xr iex 1 , 50 | .Xr mix 1 51 | .Sh AUTHOR 52 | .Bl -tag -width Ds 53 | .It Elixir is maintained by The Elixir Team. 54 | .It This manual page was contributed by Evgeny Golyshev. 55 | .It Copyright (c) 2012 Plataformatec. 56 | .It Copyright (c) 2021 The Elixir Team. 57 | .El 58 | .Sh INTERNET RESOURCES 59 | .Bl -tag -width Ds 60 | .It Main website: https://elixir-lang.org 61 | .It Documentation: https://elixir-lang.org/docs.html 62 | .It Package manager: https://hex.pm 63 | .El 64 | -------------------------------------------------------------------------------- /man/elixirc.1: -------------------------------------------------------------------------------- 1 | .\" SPDX-License-Identifier: Apache-2.0 2 | .\" SPDX-FileCopyrightText: 2021 The Elixir Team 3 | .\" SPDX-FileCopyrightText: 2012 Plataformatec 4 | .Dd April 10, 2015 5 | .Dt ELIXIRC 1 6 | .Os 7 | .Sh NAME 8 | .Nm elixirc 9 | .Nd The Elixir compiler 10 | .Sh SYNOPSIS 11 | .Nm 12 | .Op Ar OPTIONS 13 | .Ar 14 | .Sh DESCRIPTION 15 | The compiler is intended for compilation one or more files containing the Elixir source code. The files should have the extension 16 | .Em .ex . 17 | .Sh OPTIONS 18 | .Bl -tag -width Ds 19 | .It Fl o Ar directory 20 | Places the output file in the specified directory. If the directory is not specified via the option, the current working directory will be used for the purpose. 21 | .It Fl -erl Ar parameters 22 | Serves the same purpose as ELIXIR_ERL_OPTIONS 23 | .Pq see the Sy ENVIRONMENT No section . 24 | .It Fl -ignore-module-conflict 25 | Disables warnings when a module was previously defined. 26 | .It Fl -no-debug-info 27 | Disables producing debugging information. 28 | .It Fl -no-docs 29 | Disables generating documentation. 30 | .It Fl -warnings-as-errors 31 | Makes all warnings into errors. 32 | .It Fl -verbose 33 | Activates verbose mode. 34 | .It Fl - 35 | Separates the options passed to the compiler from the options passed to the executed code. 36 | .El 37 | .Sh ENVIRONMENT 38 | .Bl -tag -width Ds 39 | .It Ev ELIXIR_ERL_OPTIONS 40 | Allows passing parameters to the Erlang runtime. 41 | .It Ev ERL_COMPILER_OPTIONS 42 | Allows passing parameters to the Erlang compiler 43 | .Pq see Xr erlc 1 . 44 | .El 45 | .Sh SEE ALSO 46 | .Xr elixir 1 , 47 | .Xr iex 1 , 48 | .Xr mix 1 49 | .Sh AUTHOR 50 | .Bl -tag -width Ds 51 | .It Elixir is maintained by The Elixir Team. 52 | .It This manual page was contributed by Evgeny Golyshev. 53 | .It Copyright (c) 2012 Plataformatec. 54 | .It Copyright (c) 2021 The Elixir Team. 55 | .El 56 | .Sh INTERNET RESOURCES 57 | .Bl -tag -width Ds 58 | .It Main website: https://elixir-lang.org 59 | .It Documentation: https://elixir-lang.org/docs.html 60 | .El 61 | -------------------------------------------------------------------------------- /man/iex.1.in: -------------------------------------------------------------------------------- 1 | .\" SPDX-License-Identifier: Apache-2.0 2 | .\" SPDX-FileCopyrightText: 2021 The Elixir Team 3 | .\" SPDX-FileCopyrightText: 2012 Plataformatec 4 | .Dd February 3, 2019 5 | .Dt IEX 1 6 | .Os 7 | .Sh NAME 8 | .Nm iex 9 | .Nd The Elixir shell 10 | .Sh SYNOPSIS 11 | .Nm 12 | .Op Ar OPTIONS 13 | .Sh DESCRIPTION 14 | The interactive shell is used for evaluation, debugging and introspection of the Elixir runtime system. It is also possible to use the program for testing the work of small pieces of code escaping the stage of saving the code in a file. 15 | .Sh OPTIONS 16 | Note that many of the options mentioned here were borrowed from the Erlang shell, therefore 17 | .Xr erl 1 18 | can be used as an additional source of information on the options. 19 | .Bl -tag -width Ds 20 | {COMMON} 21 | .It Fl -dot-iex Ar file 22 | Loads the specified file instead of 23 | .Pa .iex.exs 24 | .Pq see the Sy FILES No section . 25 | .It Fl -remsh Ar node 26 | Connects to the specified node which was started with the 27 | .Fl -sname 28 | or 29 | .Fl -name 30 | options 31 | .Pq see above . 32 | .It Fl - 33 | Separates the options passed to the compiler from the options passed to the executed code. 34 | .El 35 | .Sh NOTES 36 | The following options can be given more than once: 37 | .Fl -boot-var Ns , Fl -erl-config Ns , Fl -eval Ns , Fl -rpc-eval Ns . 38 | .Sh ENVIRONMENT 39 | .Bl -tag -width Ds 40 | .It Ev ELIXIR_ERL_OPTIONS 41 | Allows passing parameters to the Erlang runtime. 42 | .El 43 | .Sh FILES 44 | .Bl -tag -width Ds 45 | .It Pa ~/.erlang.cookie 46 | Stores the magic cookie value which is used only when it wasn't specified via the option 47 | .Fl -cookie 48 | .Pq see above . 49 | If the file doesn't exist when a node starts, it will be created. 50 | .It Pa .iex.exs 51 | After 52 | .Nm 53 | starts, it seeks the file 54 | .Pa .iex.exs 55 | and, in a case of success, executes the code from the file in the context of the shell. At first the search starts in the current working directory; then, if necessary, it continues in the home directory. 56 | .El 57 | .Sh SEE ALSO 58 | .Xr elixir 1 , 59 | .Xr elixirc 1 , 60 | .Xr mix 1 61 | .Sh AUTHOR 62 | .Bl -tag -width Ds 63 | .It Elixir is maintained by The Elixir Team. 64 | .It This manual page was contributed by Evgeny Golyshev. 65 | .It Copyright (c) 2012 Plataformatec. 66 | .It Copyright (c) 2021 The Elixir Team. 67 | .El 68 | .Sh INTERNET RESOURCES 69 | .Bl -tag -width Ds 70 | .It Main website: https://elixir-lang.org 71 | .It Documentation: https://elixir-lang.org/docs.html 72 | .El 73 | --------------------------------------------------------------------------------