sonar rules in action with walkmod

23
Sonar rules in ac-on with Walkmod Raquel Pau [email protected]

Upload: raquel-pau

Post on 23-Feb-2017

456 views

Category:

Software


10 download

TRANSCRIPT

Page 1: Sonar rules in action with walkmod

Sonar  rules  in  ac-on  with  Walkmod

Raquel  Pau    [email protected]  

Page 2: Sonar rules in action with walkmod

INTRODUCTION  FROM THE BOTTOM TO THE TOP

Page 3: Sonar rules in action with walkmod

The abstract syntax tree

rpau/javalang

rpau/javalang-compiler

Page 4: Sonar rules in action with walkmod

Visitor pattern

node.accept (visitor, ctx);

Page 5: Sonar rules in action with walkmod

Exercise 1

•  Fork  &  Clone  walkmod/walkmod-sonar-plugin

•  Run:  git checkout tutorial •   Open  from  src/test/java:  – org.walkmod.sonar.tutorial.Exercise1  

•  Run  the  JUNIT  test  from  Eclipse  •  Create  the  HelloVisitor  in  the  same  package  that  modifies  the  class  name  “Foo”  per  “Hello”    

Page 6: Sonar rules in action with walkmod

Execution Workflow

Page 7: Sonar rules in action with walkmod

How to create Plugins

•  Create  a  Maven  project  – Ar-factId:  walkmod-­‐xxxx-­‐plugin  – Dependencies:  javalang-compiler  &  walkmod-core

•  Plugin descriptor:  – META-­‐INF/walkmod/walkmod-­‐xxxx-­‐plugin.xml  – Spring  configura-on  file  

•  Deployment  to  Maven  central  

Page 8: Sonar rules in action with walkmod

SONAR  RULES  GITHUB.COM/WALKMOD/WALKMOD-SONAR-PLUGIN

Page 9: Sonar rules in action with walkmod

Syntactic rules

Only  require  a  valid  AST  

Collapsible "if" statements should be merged [sonar:CollapsibleIfStatements]  

 if (file != null) { if (file.isFile() || file.isDirectory()){ /* ... */ }}

if (file != null && (file.isFile() || file.isDirectory())) { /* ... */ }

Page 10: Sonar rules in action with walkmod

Other syntactic rules

•  String literals should not be duplicated •  Useless parentheses around expressions should be removed

to prevent any misunderstanding [sonar:RemoveUselessParentheses].

•  Strings literals should be placed on the left side when

checking for equality [sonar:StringCheckOnLeV]

Page 11: Sonar rules in action with walkmod

Semantic rules

Require  type  or  symbol  resolu-on.  

•  Collection#isEmpty() should be used to test for emptiness  

if (myCollection.size() == 0) { /* ... */}

if (myCollection.isEmpty()) { /* ... */}

How  to  resolve  if  size() is  a  java.util.Collection#size()  ?  

Page 12: Sonar rules in action with walkmod

Example: UseCollectionIsEmpty

…MethodCallExpr mce = (MethodCallExpr) methodExpr;MethodSymbolData msd = mce.getSymbolData();

if (msd != null) {if (mce.getName().equals("size") && ("0".equals(((IntegerLiteralExpr) numberExpr).getValue()))) {

if(Collection.class.isAssignableFrom( msd.getMethod().getDeclaringClass())) {

Expression newExpr = new MethodCallExpr(mce.getScope(), "isEmpty"); if (n.getOperator().equals(BinaryExpr.Operator.notEquals)) {

newExpr = new UnaryExpr(newExpr, UnaryExpr.Operator.not); }

n.getParentNode().replaceChildNode(n, newExpr); }}

[sonar:UseCollec-onIsEmpty]  

Page 13: Sonar rules in action with walkmod

Symbol definitions and references

Field names should comply with a naming convention  

class MyClass { private int my_field;}

class MyClass { private int myField;}

All  my_field  references  need  to  be  updated!  

this.my_field = my_field; this.myField = my_field;

Page 14: Sonar rules in action with walkmod

 @RequiresSemanticAnalysis

@RequiresSemanticAnalysispublic class UseCollectionIsEmpty extends VoidVisitorAdapter<VisitorContext> {….}

Page 15: Sonar rules in action with walkmod

Semantic API

•  SymbolDataAware#getSymbolData()

•  SymbolDefinition#getUsages()•  SymbolReference#getSymbolDefinition()

•  ScopeAwareInterface  for  SymbolDefini-on,  SymbolReference  &  BlockStmt  –  #getVariableDefinitions()–  #getTypeDefinitions()–  #getMethodDefinitions()

•  Refactorizable#rename() Interface  for  VariableDeclara-on  &  Parameter.  Applies  safe  updates  to  all  the  references  to  that  variable/parameter.  [sonar:LocalVarsShouldComplyWithNamingConvention]

•  SemanticTest  

Page 16: Sonar rules in action with walkmod

Semantic rules testing  public class UseCollectionIsEmptyTest extends SemanticTest {

@Test public void testEqualsToZero() throws Exception { CompilationUnit cu = compile( "import java.util.List; “+ ” public class Foo { “+ ”public boolean testIsEmpty(List list){“+ ” return list.size() == 0; }}");

UseCollectionIsEmpty visitor = new UseCollectionIsEmpty(); cu.accept(visitor, null);

MethodDeclaration md = (MethodDeclaration) cu.getTypes() .get(0).getMembers().get(0); BlockStmt block = md.getBody(); ReturnStmt returnStmt = (ReturnStmt) block.getStmts().get(0); Assert.assertTrue(returnStmt.getExpr() instanceof MethodCallExpr); }}

 

Page 17: Sonar rules in action with walkmod

exercise 2

•  Open  org.walkmod.sonar.tutorial.Exercise2    

Try  to  implement  the  rule  #9  Useless imports should be removed

 

Page 18: Sonar rules in action with walkmod

Other semantic rules

•  Local variable and method parameter names should comply with a naming convention

[sonar:LocalVarsShouldComplyWithNamingConvention]

•  Useless imports should be removed [sonar:RemoveUselessImports]

•  Redundant casts should not be used [sonar:RedundantCastsShouldNotBeUsed]

•  String literals should not be duplicated

•  Local variables should not shadow class fields

 

Page 19: Sonar rules in action with walkmod

External symbol references

•  PROBLEM:  Other  files  could  contain  references  to  the  desired  node  to  modify  

•  It  is  necessary  to  design  a  two  step  process.  – First  step:  To  compute  the  required  refactorings.  

Produces  refactoring  configuraCon  – Second  step:  To  apply  the  computed  refactorings.  

Executes  walkmod-­‐refactoring-­‐plugin  

Page 20: Sonar rules in action with walkmod

External refactoring API

It  is  necessary  to  create  a  new  refactoring  chain  dynamically  

RefactorConfigurationController#getMethodRefactorRules

 Returns  the  map  of  current  refactoring  rules  and  

creates  a  refactoring  chain  if  it  is  missing.    {Foo:bar(java.lang.String s, int c) => Foo:bar(c)}  

Page 21: Sonar rules in action with walkmod

Sonar Rules examples

•  Unused method parameters should be removed [sonar:RemoveUnusedMethodParameters]  •  Method names should comply with a naming convention •  Class variable fields should not have public accessibility  

Page 22: Sonar rules in action with walkmod

General working procedure

1.  Fork  walkmod/walkmod-sonar-plugin

2.  Git  checkout  master  3.  Create  a  new  visitor  per  rule  4.  Create  a  test  5.  Define  it  in  the  walkmod-sonar-plugin.xml

6.  Create  pull  request  7.  We  deploy  the  changes  under  a  new  version  

to  the  maven  repository  

Page 23: Sonar rules in action with walkmod

Local integration tests

1.  Go  to  the  walkmod-­‐sonar-­‐plugin  directory  2.  Execute  mvn  install  3.  Replace  jars:  

1.  Open  the  following  directory:    ${HOME}/.ivy2/cache/org.walkmod/walkmod-­‐sonar-­‐plugin/jars  

2.  Replace  the  jar  that  has  the  same  name  than  walkmod-­‐sonar-­‐plugin/target/walkmod-­‐sonar-­‐plugin-­‐${version}.jar  

4.  Run  walkmod  apply  -­‐-­‐offline