Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Codenarc Part 2 Gr8Conf EU 2017

Codenarc Part 2 Gr8Conf EU 2017

A sequel to Codenarc Revisited, Codenarc Updated will outline the progress to my Fulbright Grant research and the new contributions related to Codenarc. In Part 1, the focus was mainly on formatting and teamwork. In part 2, we'll focus on performance and the bytecode level differences that are the basis for some of the more complex rules.
---------------------
Jennifer “Jenn” Strater is the co-founder of the organization Gr8Ladies. She has also organized Gr8Workshops for developers interested in an overview and crash course in Groovy technologies. She has presented on several Groovy topics at events such as the Grace Hopper Celebration of Women in Computing, Greach, Gr8Conf EU, Gr8Conf US, and Devoxx Belgium. In August 2016, Jenn started in the master’s program at the Technical University of Denmark(DTU). She is studying static analysis and compilers with a focus on Groovy with funding from the Fulbright U.S. Student Program.

jlstrater

June 01, 2017
Tweet

More Decks by jlstrater

Other Decks in Technology

Transcript

  1. @codeJENNerator Note For Those Viewing Slides Online • Bulleted text

    like this indicates the key points mentioned on a previous slide. They may not have been included in the official presentation. • If this view does not support links, the links will work in the pdf. Click the ‘download pdf’ button on the right.
  2. @codeJENNerator About Me - Took classes at the Technical University

    of Denmark and worked on a research project - Also explored Danish Culture with funding from the US Fulbright Grant program - Prior to the Fulbright Grant, I was a senior consultant at Object Partners, Inc. in Minneapolis, MN, USA. - Co-founder of Gr8Ladies and talk about women in the Groovy Community all over the world - Passionate about bring new people into the Groovy community through free introductory workshops called Gr8Workshops. - Moving to Berlin and starting at Zenjob in June 2017.
  3. @codeJENNerator Agenda • Part I Recap • What’s New Since

    Part I • Creating a Custom Rule • Bytecode Analysis and Optimization Project
  4. @codeJENNerator “CodeNarc is a static analysis tool for Groovy source

    code, enabling monitoring and enforcement of many coding standards and best practices… CodeNarc is similar to popular static analysis tools such as PMD or Checkstyle. Unlike those tools which analyze Java code, CodeNarc analyzes Groovy code.” What is ?
  5. @codeJENNerator Why use Codenarc? • Improves readability • Saves time

    with code reviews • Code with fewer bugs • Help onboard new team members
  6. @codeJENNerator ->groovy codenarc.groovy create-rule Enter your name:Jenn Strater Enter the

    rule name:TestExampleRule Enter the rule category. Valid categories are: basic braces concurrency convention design dry exceptions formatting generic grails groovyism imports jdbc junit logging naming security serialization size unnecessary unused unnecessary Enter the rule description:A test example rule that removes some unnecessary piece of code Created ./src/main/groovy/org/codenarc/rule/unnecessary/TestExampleRule.groovy Created ./src/test/groovy/org/codenarc/rule/unnecessary/TestExampleRuleTest.groovy Updated ./src/main/resources/codenarc-base-messages.properties Updated ./src/main/resources/rulesets/unnecessary.xml Updated ./src/site/apt/codenarc-rules-unnecessary.apt Updated ./CHANGELOG.txt adding to git... add 'src/main/groovy/org/codenarc/rule/unnecessary/TestExampleRule.groovy' adding to git... add 'src/test/groovy/org/codenarc/rule/unnecessary/TestExampleRuleTest.groovy' Finished
  7. @codeJENNerator TextExampleRule.groovy /*
 * Copyright 2017 the original author or

    authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 package org.codenarc.rule.unnecessary
 
 import org.codenarc.rule.AbstractAstVisitorRule
 import org.codenarc.rule.AbstractAstVisitor
 
 /**
 * A test example rule that removes some unnecessary piece of code
 *
 * @author Jenn Strater
 */
 class TestExampleRule extends AbstractAstVisitorRule {
 
 String name = 'TestExample'
 int priority = 2
 Class astVisitorClass = TestExampleAstVisitor
 }
 
 class TestExampleAstVisitor extends AbstractAstVisitor {
 
 }

  8. @codeJENNerator TextExampleRuleTest.groovy package org.codenarc.rule.unnecessary
 
 import org.codenarc.rule.Rule
 import org.junit.Test
 import

    org.codenarc.rule.AbstractRuleTestCase
 class TestExampleRuleTest extends AbstractRuleTestCase {
 
 @Test
 void testRuleProperties() {
 assert rule.priority == 2
 assert rule.name == 'TestExample'
 }
 
 @Test
 void testNoViolations() {
 final SOURCE = '''
 // todo: replace with source for passing edge case(s)
 '''
 assertNoViolations(SOURCE)
 }
 
 @Test
 void testSingleViolation() {
 final SOURCE = '''
 // todo: replace with source that triggers a violation
 '''
 assertSingleViolation(SOURCE, 1, '...')
 }
 
 @Test
 void testMultipleViolations() {
 final SOURCE = '''
 // todo: replace with source that triggers 2 violations
 '''
 assertViolations(SOURCE,
 [lineNumber:1, sourceLineText:'...', messageText:'...'], // todo: replace line number, source line and message
 [lineNumber:1, sourceLineText:'...', messageText:'...']) // todo: replace line number, source line and message
 }
 
 protected Rule createRule() {
 new TestExampleRule()
 }
 }
  9. @codeJENNerator CouldBeSwitchRule.groovy class CouldBeSwitchStatementRule extends AbstractAstVisitorRule { String name =

    'CouldBeSwitchStatement' int priority = 3 Class astVisitorClass = CouldBeSwitchStatementAstVisitor String errorMessage = 'Code could use switch statement' }
  10. @codeJENNerator CouldBeSwitchRule.groovy class CouldBeSwitchStatementAstVisitor extends AbstractAstVisitor { private BinaryExpression prev

    = null private Integer ifCounter = 0 private firstIfNode = null @Override void visitIfElse(IfStatement node) { checkIfStatementCanBeSwitch(node) super.visitIfElse(node) } private void checkIfStatementCanBeSwitch(IfStatement node) { def current = node.booleanExpression?.expression if (current instanceof BinaryExpression && isSupportedLeftExpressionType(current.leftExpression) && inSupportedOperation(current.operation)) { if (isSameLeftExpressionAsPreviousIfStatement(current.leftExpression, prev?.leftExpression)) { ifCounter++ } else { ifCounter = 1 firstIfNode = current } if (ifCounter > 2) { addViolation(firstIfNode, rule.errorMessage) ifCounter = 0 prev = null } prev = current } else { ifCounter = 0 prev = null } } . . .
  11. @codeJENNerator CouldBeSwitchRule.groovy private Boolean inSupportedOperation(Token operation) { operation.type in [Types.COMPARE_EQUAL,

    Types.KEYWORD_INSTANCEOF] } private Boolean isSupportedLeftExpressionType(def expression) { switch(expression) { case PropertyExpression: case VariableExpression: case ConstantExpression: return true default: return false } } private Boolean isSameLeftExpressionAsPreviousIfStatement(def current, def prev) { if (!prev || current.class != prev.class) { return false } switch(current) { case PropertyExpression: return isSameLeftExpressionAsPreviousIfStatement(current.objectExpression, prev?.objectExpression) && isSameLeftExpressionAsPreviousIfStatement(current.property, prev.property) case VariableExpression: return current.variable == prev?.variable case ConstantExpression: return current.value == prev.value default: false } }
  12. @codeJENNerator codenarc-base-messages.properties 
 # todo: manually sort your messages into

    the correct location
 TestExample.description=A test example rule that removes some unnecessary piece of code
 TestExample.description.html=A test example rule that removes some unnecessary piece of code
  13. @codeJENNerator codenarc-rules-unnecessary.apt 
 * {TestExample} Rule
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 <Since CodeNarc 0.24>


    
 A test example rule that removes some unnecessary piece of code
 
 Example of violations:
 
 ------------------------------------------------------------------------ -------
 // TODO: Add examples
 ------------------------------------------------------------------------ -------

  14. @codeJENNerator • Codenarc is a lot more than just formatting

    • There is still a lot of work to do • You can add your own custom rules and contribute back
  15. @codeJENNerator • Simple Groovy project • Uses an ASM reader

    and writer to read bytecode compiled using each of the groovy compiler options
  16. @codeJENNerator • Simple Groovy project • Uses an ASM reader

    and writer to read bytecode compiled using each of the groovy compiler options • Iterates over the method instructions to find the unneccessary instructions
  17. @codeJENNerator • Simple Groovy project • Uses an ASM reader

    and writer to read bytecode compiled using each of the groovy compiler options • Iterates over the method instructions to find the unneccessary instructions • Removes the instructions and outputs the new bytecode
  18. @codeJENNerator • Simple Groovy project • Uses an ASM reader

    and writer to read bytecode compiled using each of the groovy compiler options • Iterates over the method instructions to find the unneccessary instructions • Removes the instructions and outputs the new bytecode • https://github.com/jlstrater/groovy-compiler-project
  19. @codeJENNerator • There was no difference in performance • as

    explained on the mailing list • Also probable problem with benchmarking procedure
  20. @codeJENNerator • There was no difference in performance • as

    explained on the mailing list • Also probable problem with benchmarking procedure • Output file sizes are being reduced. Some by up to 10% or more.
  21. @codeJENNerator • Clean up the code and find a way

    to integrate the optimization and fixes into the existing groovy compiler
  22. @codeJENNerator Next Steps • Join the Groovy Community on Slack

    groovycommunity.com • Join the Codenarc Mailing List • Submit a PR!