Skip to content

Conversation

@eproxus
Copy link
Contributor

@eproxus eproxus commented Jul 22, 2025

This change makes rebar3 experimental manifest return macros as maps (JSON objects) to match the required ELP format.

@robertoaloi
Copy link
Contributor

@eproxus The CT failure seems unrelated, maybe re-push this one to get a green CI?

to_macros(Macros) ->
maps:from_list([to_macro(M) || M <- Macros]).

-spec to_macro(atom() | {atom() | any()}) -> {macro_key(), macro_value()}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -spec looks incorrect now. The input Value in the first clause can be any(), but the Value in output is a macro_value(), which is a binary().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and the old type can contain just a key without a value too... will fix this if you think the overall PR make sense.

@robertoaloi
Copy link
Contributor

Just to clarify and confirm this fixes the integration issue:

  • Did you test the change with ELP? If so, how?
  • What's the config that breaks ELP and how does the problem manifests in the CLI or IDE?

@eproxus eproxus force-pushed the manifest-macro-objects branch from 0774f64 to 7685638 Compare August 21, 2025 12:46
@eproxus
Copy link
Contributor Author

eproxus commented Aug 21, 2025

Just to clarify and confirm this fixes the integration issue:

  • Did you test the change with ELP? If so, how?
  • What's the config that breaks ELP and how does the problem manifests in the CLI or IDE?

Yes, using version 1.1.0+build-2025-07-21. If you generate a manifest with rebar3 as test experimental manifest and then refer to it in your .elp.toml like so:

[build_info]
file = "manifest.json"

ELP (via Zed) spits out this error:

Reading build_info file /path/to/project/manifest.json, found in /path/to/project/.elp.toml: invalid type: sequence, expected a map at line 6 column 22

Where the manifest is:

{
    "deps": [
        {
            "name": "crc32cer",
            "dir": "/path/to/project/_build/default/lib/crc32cer",
            "macros": [], // Line 6
                   % ^ column 22
            "extra_src_dirs": [],
...

Generating a manifest with this patch stops ELP from complaining.

-spec to_macro(atom() | {atom() | any()}) -> macro().
-spec to_macros(proplists:proplist()) -> macros().
to_macros(Macros) ->
maps:from_list([to_macro(M) || M <- Macros]).
Copy link
Contributor

@vkatsuba vkatsuba Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal, but, since there is already happens a loop over a list it can be make sense to simply it like

to_macros(Macros) ->
   to_macro(Macros, #{}).
   
to_macro([], Acc) ->
    Acc;
to_macro([{Key, Value} | T], Acc) when is_atom(Key) ->
    to_macro(T, Acc#{Key => Value});
to_macro([K | T], Acc) when is_atom(Key) ->
    to_macro(T, Acc#{Key => <<"true">>}).

and get rid of the function call maps:from_list/1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll keep it as is right now since it is fairly readable. We might consider using lists:foldl or a custom recursive functions, but maps:from_list is a NIF so I'd like to see some benchmark first that this really makes a difference for any practical case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, plus a list maybe will not a big it self. As I wrote above - it not a big deal, but by some reason I was think that the one list loop it always a faster then two 🙃 - but as you mention is used a NIF.

@robertoaloi
Copy link
Contributor

@eproxus Oh, I see. Are you going through the manifest.json file for a reason? As long as you have a rebar.config file, ELP will invoke the manifest plugin internally , using the EETF format.

If it makes sense, you could just drop the [build_Info] section from the .elp.toml file altogether and things should work out of the box.

Said that, yes, we should also fix this format. I also see that macros are broken in many ways with the rebar integration (we don't use it internally, so I'm not surprised). For example, the following in a rebar.config:

{erl_opts, [
    {d, 'FOO', <<>>}
]}.

Would cause (with the current rebar3):

$ elp build-info --to manifest.json

thread 'main' panicked at crates/project_model/src/json.rs:142:18:
Invalid macro in ${'FOO',<<>>}
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: elp_project_model::json::JsonProjectAppData::from_project_app_data
   3: elp_project_model::Project::as_json
   4: elp::try_main
   5: elp::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

And (with your version):

 elp build-info --to manifest.json
Failed to decode rebar build info for config file Rebar(RebarConfig { config_file: AbsPathBuf("/Users/robertoaloi/git/github/erlang-ls/erlang_ls/rebar.config.script"), profile: Profile("test") }): expected a list, got: Map(Map { map: {Atom(Atom { name: "TEST" }): Binary(Binary { bytes: [116, 114, 117, 101] }), Atom(Atom { name: "FOO" }): Binary(Binary { bytes: [] })} })

@eproxus
Copy link
Contributor Author

eproxus commented Aug 21, 2025

We were using it manually as a stop gap to get it to work (probably because of the problem fixed by #2963) and discovered this. It just felt like a bug.

@robertoaloi Ok, so this PR improves the situation slightly but not completely. Would you like it merged as is, and then you can fix the other problems later if needed? Since we don't really use the JSON manifest we don't really care either way 😄

@robertoaloi
Copy link
Contributor

@eproxus Sounds like a plan.

@eproxus eproxus marked this pull request as ready for review August 21, 2025 13:40
Copy link
Contributor

@robertoaloi robertoaloi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, apart from the incorrect spec.

@eproxus eproxus force-pushed the manifest-macro-objects branch from 7685638 to 6aaac21 Compare August 21, 2025 13:50
@eproxus
Copy link
Contributor Author

eproxus commented Aug 21, 2025

@robertoaloi Simplified the type specs to match the original version (plus a bug fix {atom() | any()}{atom(), any()}).

Ready to merge from my side. Let me know if you have any more concerns.

This change makes `rebar3 experimental manifest` return macros as maps
(JSON objects) to match the required ELP format.
@eproxus eproxus force-pushed the manifest-macro-objects branch from 6aaac21 to 50e5b85 Compare August 21, 2025 13:59
@ferd ferd merged commit b62659b into erlang:main Aug 21, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants