sonar rules in action with walkmod
TRANSCRIPT
![Page 2: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/2.jpg)
INTRODUCTION FROM THE BOTTOM TO THE TOP
![Page 3: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/3.jpg)
The abstract syntax tree
rpau/javalang
rpau/javalang-compiler
![Page 4: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/4.jpg)
Visitor pattern
node.accept (visitor, ctx);
![Page 5: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/5.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/6.jpg)
Execution Workflow
![Page 7: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/7.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/8.jpg)
SONAR RULES GITHUB.COM/WALKMOD/WALKMOD-SONAR-PLUGIN
![Page 9: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/9.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/10.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/11.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/12.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/13.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/14.jpg)
@RequiresSemanticAnalysis
@RequiresSemanticAnalysispublic class UseCollectionIsEmpty extends VoidVisitorAdapter<VisitorContext> {….}
![Page 15: Sonar rules in action with walkmod](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/15.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/16.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/17.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/18.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/19.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/20.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/21.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/22.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022042601/58ae91a41a28abdf068b5d93/html5/thumbnails/23.jpg)
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