Skip to content
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

Function inlining #3805

Open
lyriccoder opened this issue Feb 24, 2021 · 1 comment
Open

Function inlining #3805

lyriccoder opened this issue Feb 24, 2021 · 1 comment

Comments

@lyriccoder
Copy link

Hi SPOON contributors. How can I make inline of the function?

I found a way to search for the folllowing data (so, I can find all those objects via your framework):

CtMethod targetMethodDeclaration;
CtMethod extractedMethodDeclaration;
CtInvocation invocation;
Launcher launcher

It will look like:

class Test {
    void targetMethodDeclaration() {
         int e = 5;
         int res = extractedMethodDeclaration(e);
         return res;
    }
    
    int extractedMethodDeclaration(int b) {
          int a = 0;
         ++a;
         return a;
    }
}

Is it possible to inline extractedMethodDeclaration into targetMethodDeclaration:

class Test {
    void targetMethodDeclaration() {
          int e = 0;
          int a = 0;
          ++a; 
           int res = a;
         return res ;
    }
    
    void extractedMethodDeclaration() {
          int a = 0;
         ++a;
         return a;
    }
}

Or at least can I inline it with void function? Then I can add functionlity which can insert function with return types.

I see that I can add statements, but I can't apply the changes. Also, it is possible to apply changes on the cloned model, but in different places to get different Java files?

public class InlineOpportunity {
    protected final CtModel astTree;
    private CtMethod targetMethodDeclaration;
    private CtMethod extractedMethodDeclaration;
    private CtInvocation invocation;

...
}

Suppose I have 1 model and all methods (actually, each opportunity has a link to a single model):

for (InlineOpportunity opp: opportunities) {
            // Do i need to copy it? How can i Do it?
           //  CtPackage cloneOfAstTree = opp.getAstTree().getRootPackage().clone();

            CtBlock block = opp.getTargetMethodDeclaration().getBody();
            int counter = 1;
            int statementsSize = block.getStatements().size();
            for (CtStatement st : block.getStatements()) {
                while ((st != opp.getInvocation()) && (counter < statementsSize)) {
                    ++counter;
                }
                if (counter == statementsSize) {
                    break;
                }
                CtBlock block_to_insert = opp.getExtractedMethodDeclaration().getBody();
                for (CtStatement inserted_st: block_to_insert.getStatements()) {
                    st.insertAfter(inserted_st);
                }
                st.delete(); // If I look at opp.getTargetMethodDeclaration().getBody line, i see that change have been made
                String s = opp.getAstTree().getRootPackage().getOriginalSourceFragment().getSourceCode(); // Here I see that the changes are not applied for the whole model (class)
                break;
            }
        }

How can I apply chages? How can I make a clone of a model to apply different changes (I have lots of invocations)? I need to save them into a different file.

Originally posted by @lyriccoder in #3251 (comment)

@andrewbwogi
Copy link
Contributor

andrewbwogi commented Feb 28, 2021

Hello @lyriccoder, if each element in a list of InlineOpportunity should represent a separate file, a rough implementation of inlining in assignment statements is:

for (InlineOpportunity opp: opportunities) {
    if(opp.getInvocation().getParent() instanceof CtRHSReceiver) {

        // stash original element
        CtInvocation clonedInvocation = opp.getInvocation().clone();

        // clone replacing elements
        List<CtStatement> statements = opp.getExtractedMethodDeclaration().getBody().getStatements();
        List<CtStatement> clonedStatements = new ArrayList<>();
        for (CtStatement s : statements) {
            clonedStatements.add(s.clone());
        }

        // make the inlining
        int size = clonedStatements.size();
        for(int i = 0; i<size-1;i++){
            ((CtStatement)opp.getInvocation().getParent()).insertBefore(clonedStatements.get(i));
        }
        CtExpression returnExpression = ((CtReturn)clonedStatements.get(size-1)).getReturnedExpression();
        opp.getInvocation().replace(returnExpression);

        // print the resulting class
        System.out.println(ctClass);

        // reset model
        returnExpression.replace(clonedInvocation);
        for (CtStatement s : clonedStatements) {
            s.delete();
        }
    }
}

To reset the model back to its original state, element clones are inserted into the model and deleted at the end of each loop and the stashed original element is put back. You get the prettyprint of the changed model by calling toString on it.

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

No branches or pull requests

2 participants