DragonKnightOfBreeze / Paradox-Language-Support

IDEA Plugin: Paradox Language Support.
https://windea.icu/Paradox-Language-Support
MIT License
36 stars 4 forks source link

Inference for inline_script parameters from usages #54

Closed TTFTCUTS closed 2 months ago

TTFTCUTS commented 8 months ago

As we expand the use of inline scripts in Gigastructural Engineering, it has become useful in several places to pass whole blocks of code as parameters. It would be very helpful if the parameters could be evaluated, much like how the scripts themselves infer context from where they are used.

image image

I understand that this might be a tricky request to fulfill, but being able to catch typos in these situations without making mock-ups first would be super useful.

Thank you, once again, for all of your hard work.

DragonKnightOfBreeze commented 8 months ago

It's already implemented for simple cases.

DragonKnightOfBreeze commented 8 months ago

image

While the first option can enable the argument value inference (for scripted_triggers, scripted_effects, inline_scripts, single value or multiline), the second option can enable the inline script inference (for inline script files). And the leaving three options enable scope context inference in several situations, which may significantly affects performance.

If it's not work:

DragonKnightOfBreeze commented 8 months ago

Plz feedback your experience and ideas.

TTFTCUTS commented 8 months ago

Well, those settings are already enabled: image

The current version of the plugin which I have is 1.2.4, but that's also the newest version the plugin settings give me...

A minimal example script which just takes one parameter and places it in-situ is the simplest case that I can think of image

But when it's used the parameter doesn't seem to be checked at all, and doesn't receive syntax highlighting. image

So I'm not sure if I'm understanding what those settings are meant to be doing correctly.

DragonKnightOfBreeze commented 8 months ago

Update plugin to 1.2.5 on github releases and see what happens?

DragonKnightOfBreeze commented 8 months ago

Also open xxx_traits.txt and see what happens to the inline script usages in these files?

TTFTCUTS commented 8 months ago

I think I see what's going on now.

The trait files seem to work correctly, and if I add a second parameter which is the right hand side of an expression, like this: image

Then that parameter seems to work as expected, but the one which is meant to just put its whole content there does not. image

DragonKnightOfBreeze commented 8 months ago

Should be a reproduced bug. 🙁

TTFTCUTS commented 8 months ago

It seems to understand situations where the passed parameter is the right side of an expression, but not where it's a scope, or when it's a whole line or multiple lines. image

image

DragonKnightOfBreeze commented 8 months ago

image

Found out it's a bug about double quotes.

DragonKnightOfBreeze commented 8 months ago

A question, when typo modifier after v =, should plugin provide completion items and make inserted text surrounding with double quotes after applied, or just do not provide completion items (for there are no double quotes after v = and whole line or multiline parameter value must be used in double quotes) ?

TTFTCUTS commented 8 months ago

I am not entirely sure what you mean, but I do think it should still provide completion when typing inside quotes.

I think the ideal behaviour would be if it acted the same as a normal code block when inside quotes, almost as if they were braces instead, maybe only when multi-line? Unsure.

If I could type inside the parameter and it acts the same as where the code ends up being, that would be perfect - so in the very basic example again: image image

Thank you for looking into this, it should be really useful for us.

@adriangaro probably has opinions on this too, as the only other person I know of who is doing weird things with inlines.

DragonKnightOfBreeze commented 8 months ago

What do i say is that when I just typo modifier after v = (neither v = " or v = "\n, \n means line break), should plugin provide completions for statements such as modifier = {...}? And if should , also make it surrounds with double quotes, and then, there is some text like v = "modifier = {...}"

TTFTCUTS commented 8 months ago

Oh! Without quotes it should probably only suggest things which don't need quotes, like possible right-side values for expressions if the parameter is used that way.

adriangaro commented 8 months ago

Would also be neat if the plugin can't easily infer a type, if somehow we could provide it through a comment in the line or something.

Something like

# @param <param name> - <type>

# so something like below

# @param trigger - trigger block/triggers

Mostly it is an example, but comments should probably avoid the $ symbol since they do get interpolated in the comments too, and with multi line strings they go over next line outside the comment.

The types could be some predefined ones, or somehow some types from the cwt definitions.

I have a lot of cases where the parameters can't be inferred due to using intermediary inlines for indirection/conditional logic, which breaks very quickly any kind of inference of type.

adriangaro commented 8 months ago

Some examples are

https://github.com/Stellaris-Evolved/stellaris-evolved/blob/V0.9R8/common/inline_scripts/jobs/inline_evolved_job.txt

https://github.com/Stellaris-Evolved/stellaris-evolved/blob/V0.9R8/common/inline_scripts/jobs/inline_evolved_job_no_desc.txt

https://github.com/Stellaris-Evolved/stellaris-evolved/blob/V0.9R8/common/inline_scripts/jobs/inline_evolved_job_with_desc.txt

The first inline calls either of the following two depending on one of the parameters passed to the first one and delegates the rest.

adriangaro commented 8 months ago

Also due to the interpolation of the $job$ parameter into the modifier, the plugin has no idea that parameter is a job, so no autocomplete.

Being able to annotate that job is of the type job, would allow better highlighting.

I know it's a tall ask but would be really cool to be able to annotate parameters types, and maybe even add docs so they appear in context windows.

adriangaro commented 8 months ago

If type annotation/comments are added, especially for triggered blocks, it would be amazing if the scope type could also be specified. (Yet again this is a nice to have in the context of inline script parameters, or parameters in general).

Thanks for the amazing work as always!

adriangaro commented 8 months ago

Another case for annotation would be for union types for a parameter, if it can take some specific values.

In the inlines above, display is such a variable which can access only some specific values.

Probably for this maybe, the enunarations could somehow be declared in the project as a cwt definition and referenced?

Mostly spitballing on this, so take everything with a grain of salt, whichever variant would be easiest (if it will get handled) for type annotations, I'll be extremely happy.

DragonKnightOfBreeze commented 8 months ago

Magic comment or annotation comment is a good idea since it's already used by JetBrains officially in various template languages (e.g. JSP and FreeMarker), and I once considered this way. But, the standards are to be determined, these is not only type annotation comments (or, cwt config annotation comments), but also some documentation comments and even scope context comments.

DragonKnightOfBreeze commented 8 months ago

Paradox-Language-Support-1.2.6.zip

Here is a pre-release to support inference for whole line / multiline parameter values

TTFTCUTS commented 8 months ago

Happy to say the first example above is highlighting now, but sadly it seems to be too complex for the plugin to properly infer context for, probably due to an inline call in the chain using a parameter in the script name.

image

This is so much nicer than before though, so thank you!

DragonKnightOfBreeze commented 8 months ago

What about inference for these inline script files, does it work well?

TTFTCUTS commented 8 months ago

More simple scripts work very well: image

The ones in the previous message don't, but that's probably because of these:

giga_switch image

giga_toggled_code image

Which conditionally leads to two scripts, giga_toggled_code_case_0 and giga_toggled_code_case_1, the first of which is empty, for only including code if the $toggle$ input is non-zero.

TTFTCUTS commented 8 months ago

Technically speaking even if they were to infer everything correctly it would still break, as those toggles would resolve to 0 due to being cross-mod compatibility values, 0 when the other mod is not loaded and overwritten by that other mod to be 1.

So if the plugin somehow manages to untangle the flow in there, it would always end up leading to the empty giga_toggled_code_case_0 because has_bug_branch is always zero in our development environment.

Some kind of override annotation would be required at very least to point it at giga_toggled_code_case_1 instead, perhaps by telling giga_switch to always consider its value parameter to be 1 for the sake of inference, or to treat has_bug_branch as 1 or something... it's awkward.

DragonKnightOfBreeze commented 8 months ago

Emmmmmmmmmmmmm... How do Chinese modders comment on your foxy?

TTFTCUTS commented 8 months ago

I... don't understand what you mean.

What I mean to say by the previous comment is that I realised that the inference could never work for that particular script without extra hints because of the way we have structured it. It would always discard the parameters because their use is conditional upon another mod being present (because has_bug_branch is 0 when the Bug Branch mod is not present).

It seems to be working very well outside of those very complicated situations though, thank you for your efforts.

DragonKnightOfBreeze commented 8 months ago

What I mean is that ... these are too many usages of paradox scripts' advance (or even very tricky) features in your mods, and so do some Chinese moddders'. Is may be sometimes necessary and convenient, but it also make paradox's languages not simple (or, not simple txt), and so do my plugin and cwtools.

TTFTCUTS commented 8 months ago

I expected this case would probably be too complex to reasonably parse, I didn't mean for it to sound like a complaint or anything. It is an ideal example of where an annotation could be useful though.

DragonKnightOfBreeze commented 8 months ago

I found out that the best way to provide advance language featues for implicit things, like parameter an event target's scope context, is just extended cwt config, rather than special comment in script files, or stupid inference.

DragonKnightOfBreeze commented 8 months ago

Just look at this:

# test.cwt
definitions = {
    ### some documentation
    ## scopes = { this = country root = country }
    ## definition_type = scripted_trigger
    some_trigger
}
# test.txt
some_trigger = {
    # trigger declaration
}

And for on actions and game rules there are already some special cwt config files to provide additional information such as documentation, scope countext info, overridden config, event type, etc. They may be optimized.

And for parameters and value set values (e.g. event_target and variable), there can besome other special cwt config files.

adriangaro commented 8 months ago

where does one place these cwt configs

DragonKnightOfBreeze commented 8 months ago

It shall be mod-local (in .config which is under mod root directory) so that all mods can have its own extended cwt config files in a hidden directory to let the plugin to provide more support. but currently user-defined cwt config files are project-local (in .config which is under project root directory), and each project & each game type has a config group. May mod-local and project-local cwt configs are both supported. There may be some refactoring, I'm not very sure.

TTFTCUTS commented 8 months ago

I found a new minor failure state:

The plugin seems to not allow inline_script calls inside a parameter in some places that they should be allowed. In this case, inside the body of a building definition. image Copying the same code into the script itself is accepted correctly: image

Aside from this, it has been working very well and been very helpful, thank you for figuring this all out!

adriangaro commented 8 months ago

Is there a way of providing a cwt config for inline scripts then? I understand how it can be done now for effects/triggers, but for inlines i imagine it must be quite different

adriangaro commented 8 months ago

Also another minor example where scope inference doesn't work

image

the inline there has no highlighting inside it, (this is in the context of economic categories)

image

adriangaro commented 8 months ago

Another small issue is with escaped characters inside multi line strings

image

DragonKnightOfBreeze commented 8 months ago

Related optimizations and bug fixes will be resolved in 1.3.0 aka the next plugin version, mainly inference and documentation from custom cwt config, anf some other misc bugs. Should be finished in several weeks for there are some new games I will enjoy.

DragonKnightOfBreeze commented 8 months ago

image

image

image

Features that supports custom documentation and scope context based on custom cwt files are implemented in v1.3.0 (in beta status).

See: https://windea.icu/Paradox-Language-Support/#/en/config.md

adriangaro commented 7 months ago

Looking at the definitions, how can one specify the parameter type?

Also had some success defining the scripted effects as engine effects (since the above cannot mention parameter type and cardinality yet. Only issue is that the scripted effect itself does not use the below definition (makes sense since the below defines engine effects). Although probably doing the below is not intended

image

DragonKnightOfBreeze commented 7 months ago

@adriangaro What's the parameter type? identifier between ':' and ']'? It's nothing special, can be 'some_key' or '' or some others.

for usage about aliases, you can refer to buitin config files and the guidance document.

adriangaro commented 7 months ago

The identifier type is a scripted effect, mostly used the above so i could specify parameter type, since it is one of the more important use case to detail those.

I used those exact documents to try to use alias (since it fit this usage). But yeah ideally if the parameters definitions you added could support parameter type, it would be great.

Also seems the below, does not seem to set the event target scope, used the https://windea.icu/Paradox-Language-Support/#/en/config.md as reference

values = {
    value[event_target] = {
         ## replace_scopes = { this = leader }
        tec_aiauth_pre_refragment
         ## replace_scopes = { this = leader }
        tec_aiauth_planetary_governing_node
         ## replace_scopes = { this = leader }
        tec_aiauth_ruler
         ## replace_scopes = { this = pop }
        tec_temp_pop
         ## replace_scopes = { this = leader }
        tec_aiauth_councilor
         ## replace_scopes = { this = leader }
        tec_replaced_ruler
         ## replace_scopes = { this = species }
        tec_ai_species
         ## replace_scopes = { this = species }
        tec_robot_search_species
         ## replace_scopes = { this = leader }
        tec_aiauth_pre_refragment
    }
}
adriangaro commented 7 months ago

Also doing the below

definitions = {
    ## replace_scopes = { this = leader prev = country }
    ## type = scripted_effect
    tec_country_refragment_aiauth_node
}

seems to not set the prev scope image

DragonKnightOfBreeze commented 7 months ago

It's mentioned that you can use both literal and template expression as the key. For example, 'tec_value[xxx]_species' should matches any literal starts with 'tec_' and ends with '_species', no more limits for value[xxx]. Designed so, but not tested. And alias is for declaration configs, not special configs like this.

DragonKnightOfBreeze commented 7 months ago

prev cannot be replaced by ## replace_scopes, at least for PLS.

DragonKnightOfBreeze commented 7 months ago

It's still a very beta feature and it's better to be discussed on somewhere else, like, just, discord.

DragonKnightOfBreeze commented 7 months ago

https://discord.gg/RbU5U5TU