GithubHelp home page GithubHelp logo

Comments (7)

ketkarameya avatar ketkarameya commented on June 8, 2024

is the expected code (we want to retain the braces right?)

class SomeClass(
    private val expChecker: ExpChecker
) {
    fun someFunc(): SomeValue {
        return expChecker.check(Experiments.ExpName) {
             {
               logger.log("on branch called")
               SomeValue.NewValue
            }
        }
    }
}

I am assuming you wrote a feature flag api cleanup rule specifically for your custom API, which produced the above change, where the off branch is elided. Could you share that with me?

from piranha.

K1rakishou avatar K1rakishou commented on June 8, 2024

Sorry forgot to mention what it's expected to look like:

class SomeClass(
    private val expChecker: ExpChecker
) {
    fun someFunc(): SomeValue {
        logger.log("on branch called")
        return SomeValue.NewValue
    }
}

Basically the code is extracted from the on lambda and then inserted in-place. The braces are to be removed too because they are not just braces in Kotlin but a lambda function.

But it doesn't work because of return. It will also probably not work if the result of that expression were to be assigned to a variable and probably many other cases that I can't think of right now.

I am assuming you wrote a feature flag api cleanup rule specifically for your custom API, which produced the above change, where the off branch is elided.

Yes, we wrote a custom rule. Here is the full rule.

[[rules]]
name = "expchecker_check"
query = """(
(call_expression
    (call_expression
        (navigation_expression
            (simple_identifier) @expchecker_field
            (navigation_suffix (simple_identifier) @type)
        )
        (call_suffix
            (type_arguments
                (type_projection[
                    (user_type (_)
                    )
                ])
            )?
            (value_arguments
                (value_argument[
                    (navigation_expression(_) (navigation_suffix (simple_identifier) @experimentName)
                    )]
                )
            )
        )
    )
    (call_suffix ( annotated_lambda
        (lambda_literal [
                (statements(call_expression
                    (simple_identifier) @expchecker_block
                    (call_suffix (annotated_lambda
                            (lambda_literal[
                                (statements)@takenNode
                            ]))
                    ))
                )
        ]))
    )
)@ReplacedNode

(#eq? @expchecker_field "expChecker")
(#eq? @experimentName "@experiment_name")
(#eq? @expchecker_block "@taken_expchecker_lambda_name")
(#eq? @type "check")
)"""
replace_node = "ReplacedNode"
replace = "@takenNode"
holes=["taken_expchecker_lambda_name", "experiment_name"]

And then in substitutions taken_expchecker_lambda_name is going to be assigned on and experiment_name is going to be assigned ExpName,

For now, my idea to fix this is to wrap multi line code into a Kotlin's run function (think of it as of a lambda function which is invoked right away and is also then inlined directly into the JVM bytecode by Kotlin compiler). So it will look like this:

class SomeClass(
    private val expChecker: ExpChecker
) {
    fun someFunc(): SomeValue {
        return run {
            logger.log("on branch")
            SomeValue.NewValue
        }
    }
}

Not sure how to do this right now, just an idea in case there is no simple solution.

from piranha.

ketkarameya avatar ketkarameya commented on June 8, 2024

sorry! This issue completely slipped off my mind.

(call_expression
    (call_expression
        (navigation_expression
            (simple_identifier) @expchecker_field
            (navigation_suffix (simple_identifier) @type)
        )
        (call_suffix
            (type_arguments
                (type_projection[
                    (user_type (_)
                    )
                ])
            )?
            (value_arguments
                (value_argument[
                    (navigation_expression(_) (navigation_suffix (simple_identifier) @experimentName)
                    )]
                )
            )
        )
    )
    (call_suffix ( annotated_lambda
        (lambda_literal [
                (statements(call_expression
                    (simple_identifier) @expchecker_block
                    (call_suffix (annotated_lambda
                            (lambda_literal[
                                (statements)
                            ])@takenNode )
                    ))
                )
        ]))
    )
)@ReplacedNode
(#eq? @expchecker_field "expChecker")
(#eq? @experimentName "@experiment_name")
(#eq? @expchecker_block "@taken_expchecker_lambda_name")
(#eq? @type "check")
)```

^ This query shud work ( I tried on ts-kt)

from piranha.

ketkarameya avatar ketkarameya commented on June 8, 2024

is ur codebase open source?

from piranha.

K1rakishou avatar K1rakishou commented on June 8, 2024

No, it's not open-source.

So the above query removes everything except for the lambda body now. So instead of this code:

class SomeClass(
    private val expChecker: ExpChecker
) {
    fun someFunc(): SomeValue {
        return logger.log("on branch")
               SomeValue.NewValue
    }
}

It now produces this code:

class SomeClass(
    private val expChecker: ExpChecker
) {
    fun someFunc(): SomeValue {
        return {
               logger.log("on branch")
               SomeValue.NewValue
        }
    }
}

Which might work in some languages, but not in Kotlin, because in Kotlin this block:

return {
   logger.log("on branch")
   SomeValue.NewValue
}

basically means return a lambda. Which in this case is a compilation error. It's possible to fix this by adding () at the end (invoke lambda right away), like so:

return {
       logger.log("on branch")
       SomeValue.NewValue
}()

But I don't know how to insert new text into the code using piranha rules. Is this possible? If that is possible then I can figure out the rest.

from piranha.

ketkarameya avatar ketkarameya commented on June 8, 2024

yes inserting text is possible as an "update" operation.
so wait, do u want :

return {
       logger.log("on branch")
       SomeValue.NewValue
}()

or

 return run {
            logger.log("on branch")
            SomeValue.NewValue
        }

Either shud be possible

u can update ur replace to replace = run @takenNode ? or replace = @takenNode()?

from piranha.

K1rakishou avatar K1rakishou commented on June 8, 2024

Yes, this works. Thank you very much!

from piranha.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.