New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature] transform specific meta variables #723
Comments
This can be accomplished today by writing two rules and running them repeatedly until there are no more matches:
and
|
List meta transformation may be related to this. We need a way to select a list of nodes. |
List comprehensions seem artificially limiting. What it i want to transform groups of N items together, e.g. convert |
@emosenkis would you like to elaborate more on the grouping and converting? I am interested in alternative ways to transformations. |
I think what I was trying to express is that I don't think transformations are the right abstraction here. ast-grep is an incredibly powerful framework for transforming code and it doesn't make any sense to me to create a second, much less capable, mechanism for transforming code. Why not instead allow rules to be run ast-grep over the metavariables? The config might look something like this:
I'm combining a few ideas here, each of which can be accepted or rejected independently:
|
Thank you for the detailed explanation! I really appreciate your informative input! 😃 I will also share my thoughts about the suggestions:
This is a nice idea and it will be very powerful! My concern is whether nesting rules/referencing rules will be too complex for users to understand.
I would prefer the latter solution by using
The format of transformation is discussed in #436. I also proposed a mini-bash-like scripting language for fix templates. I eventually withdrew the proposal because it is too likely to evolve into another complex DSL hard to learn. I also had not designed the escaping mechanism for the fix lang, say, if users want to change So I decided to release the YAML transformation at first and looks like the solution has worked fine. I really like the idea of applying rule to a sub-region of code and composing a larger rewrite. Let me think more about it. |
Contemplating on the essence of ast-grep rewriting, I found apply-rule is a nice fit for sub meta variable transformation. ast-grep rewrite ruleThe mental model of ast-grep is like:
Rewrite list with Python's mindsetPreviously I'm thinking about using list comprehension to transform multiple nodes. Indeed it is limited. I was previously imagining something like the pseudo Python code below [
rewrite(node)
for node in meta_var_list
if node.matches(filter_rule)
] So that I can generate a list of fix strings that correspond to meta_var_list. ','.join(rewrite for node in list if filter) The YAML transformation for the fake code above will be like
What's missing in list comprehension?
ast-grep's rule does not have the issues above. Since
What's missing in rule-based rewrite?Why can't we implement list comprehension based on our current rule?
|
The simpler way: applyRule
Also, applyRule transformation is orthogonal to powerful fixer, i.e.
Click to see the comparison of expansion and applyRule to remove a key-value pair in a dictionary/objectExpansion rule:
kind: pair # find the pair
has:
field: key
regex: test
fix:
template: '' # remove the pair
expandEnd: # remove the comma
regex: ',' Apply Rules utils:
pairs: # find pair
kind: pair
has:
field: key
regex: test
rule:
kind: object # find parent
pattern: $OBJ
has:
matches: pairs
stopBy: end
transform:
NEW_OBJ: # transform parent
applyRules:
source: $OBJ
rules:
- removePair
- removeComma
rewriter:
removePair:
rule: { matches: pairs } # repeat matching
fix: ''
removeComma:
rule:
regex: /,/
follows: { matches: pairs } # repeat matching
fix: ''
fix: '$NEW_OBJ' # replace the parent Concerns
|
Withdrawn Proposal ⭐ SuggestionIt is impossible to transform a multiple-meta-variable match at the moment. We can only move multi-var match around in the fix. Promposal: rule:
pattern: $$$LISTS
transform:
NEW_LIST:
source: $$$LISTS
item: $ITEM
rewrite: rewriteWith($ITEM)
includeUnnamed: true # optional, default to false
fix: useNew($$$NEW_LIST) 💻 Use CasesSuppose we have this code. import {A, B, C} from 'lib' We want to transform it to import A from 'lib/a'
import B from 'lib/b'
import C from 'lib/c' This can be achieved by something similar to rule:
pattern: import {$$$IMPORTS} from 'lib'
transform:
NEW_IMPORTS:
source: $$$LISTS
item: $ITEM
rewrite: import $ITEM from 'lib/$ITEM'
includeUnnamed: false # optional Questions
|
All sub-tasks are done! |
⭐ Suggestion
It is impossible to apply rules/transformations to specific sub nodes in the matching.
We can only move multi-var match around in the fix.
It is possible to introduce a apply sub rules to matched variables / variable list.
Promposal:
💻 Use Cases
Suppose we have this code.
We want to transform it to
This can be achieved by something similar to
Tasks
The text was updated successfully, but these errors were encountered: