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. Codenarc Revisited: Part 2 Jenn Strater @codeJENNerator

  2. @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.
  3. @codeJENNerator https://speakerdeck.com/jlstrater/codenarc-part-2-gr8conf-eu-2017 Follow Along

  4. @codeJENNerator About Me

  5. @codeJENNerator About Me Starting at Zenjob in Berlin on Monday

    June 5!
  6. @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.
  7. @codeJENNerator Background

  8. @codeJENNerator Background • Uses Codenarc • Has written a Custom

    Rule • Contributed back to Codenarc
  9. @codeJENNerator Agenda • Part I Recap • What’s New Since

    Part I • Creating a Custom Rule • Bytecode Analysis and Optimization Project
  10. Recap of Part I https://www.youtube.com/watch?v=3v18NB7pyCY

  11. @codeJENNerator What is ?

  12. @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 ?
  13. @codeJENNerator Why use Codenarc? • Improves readability • Saves time

    with code reviews • Code with fewer bugs • Help onboard new team members
  14. @codeJENNerator Terms Formatting Space After Switch Braces for Class Trailing

    Whitespace
  15. @codeJENNerator Not Just Formatting • Concurrency • JDBC • Security

    • Complexity
  16. @codeJENNerator Setup Plugin

  17. One Year Later https://github.com/CodeNarc/CodeNarc/blob/master/CHANGELOG.txt

  18. None
  19. None
  20. None
  21. @codeJENNerator What coming next?

  22. @codeJENNerator GR8Conf Hackergarten

  23. @codeJENNerator 0.28.0

  24. @codeJENNerator Creating a Custom Rule

  25. @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
  26. @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 {
 
 }

  27. @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()
 }
 }
  28. @codeJENNerator Could Be Switch Rule

  29. Switch in Groovy http://mrhaki.blogspot.dk/2009/08/groovy-goodness-switch-statement.html

  30. @codeJENNerator CouldBeSwitchRule.groovy class CouldBeSwitchStatementRule extends AbstractAstVisitorRule { String name =

    'CouldBeSwitchStatement' int priority = 3 Class astVisitorClass = CouldBeSwitchStatementAstVisitor String errorMessage = 'Code could use switch statement' }
  31. @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 } } . . .
  32. @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 } }
  33. @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
  34. @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
 ------------------------------------------------------------------------ -------

  35. @codeJENNerator Limitations of Codenarc

  36. @codeJENNerator Codenarc Conclusion

  37. @codeJENNerator

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

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

    • There is still a lot of work to do
  40. @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
  41. @codeJENNerator Bytecode Analysis and other forms of static analysis in

    Groovy
  42. Groovy Compiler Project https://jlstrater.github.io/groovy-compiler-project/html/index.html

  43. None
  44. None
  45. @codeJENNerator Legacy

  46. @codeJENNerator Invoke Dynamic

  47. @codeJENNerator Static Compilation

  48. @codeJENNerator Indy vs Static Compilation

  49. @codeJENNerator Potential for Optimization

  50. None
  51. None
  52. @codeJENNerator https://github.com/apache/groovy/blob/master/src/main/ org/codehaus/groovy/classgen/asm/StatementWriter.java

  53. @codeJENNerator Post Pass Optimization Project

  54. @codeJENNerator

  55. @codeJENNerator • Simple Groovy project

  56. @codeJENNerator • Simple Groovy project • Uses an ASM reader

    and writer to read bytecode compiled using each of the groovy compiler options
  57. @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
  58. @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
  59. @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
  60. Results https://jlstrater.github.io/groovy-compiler-project/ bytecode/index.html

  61. @codeJENNerator

  62. @codeJENNerator • There was no difference in performance

  63. @codeJENNerator • There was no difference in performance • as

    explained on the mailing list
  64. @codeJENNerator • There was no difference in performance • as

    explained on the mailing list • Also probable problem with benchmarking procedure
  65. @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.
  66. @codeJENNerator Bytecode Analysis Next Steps

  67. @codeJENNerator

  68. @codeJENNerator • Clean up the code and find a way

    to integrate the optimization and fixes into the existing groovy compiler
  69. @codeJENNerator Conclusion

  70. @codeJENNerator Next Steps • Join the Groovy Community on Slack

    groovycommunity.com • Join the Codenarc Mailing List • Submit a PR!
  71. @codeJENNerator Questions? https://flic.kr/p/5DeuzB