All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.walkmod.sonar.visitors.SingularField Maven / Gradle / Ivy

/* 
  Copyright (C) 2016 Raquel Pau.
 
 Walkmod is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 Walkmod is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public License
 along with Walkmod.  If not, see .*/
package org.walkmod.sonar.visitors;

import java.util.Iterator;
import java.util.List;

import org.walkmod.javalang.ast.Node;
import org.walkmod.javalang.ast.SymbolData;
import org.walkmod.javalang.ast.SymbolReference;
import org.walkmod.javalang.ast.body.FieldDeclaration;
import org.walkmod.javalang.ast.body.MethodDeclaration;
import org.walkmod.javalang.ast.body.ModifierSet;
import org.walkmod.javalang.ast.body.VariableDeclarator;
import org.walkmod.javalang.ast.expr.AnnotationExpr;
import org.walkmod.javalang.ast.expr.Expression;
import org.walkmod.javalang.ast.expr.MethodCallExpr;
import org.walkmod.javalang.ast.expr.VariableDeclarationExpr;
import org.walkmod.javalang.ast.stmt.BlockStmt;
import org.walkmod.javalang.ast.stmt.ExpressionStmt;
import org.walkmod.javalang.ast.stmt.Statement;
import org.walkmod.javalang.compiler.symbols.RequiresSemanticAnalysis;
import org.walkmod.javalang.visitors.VoidVisitorAdapter;
import org.walkmod.walkers.VisitorContext;

/*
 * A field that's only used by one method could perhaps be replaced by a local variable.*/
@RequiresSemanticAnalysis
public class SingularField extends VoidVisitorAdapter {

   @Override
   public void visit(FieldDeclaration fd, VisitorContext ctx) {
      List annotations = fd.getAnnotations();
      boolean isNotInjectable = (annotations == null || annotations.isEmpty());
      int modifiers = fd.getModifiers();
      SymbolData sd = fd.getType().getSymbolData();

      if (isNotInjectable && ModifierSet.isPrivate(modifiers) && !ModifierSet.isStatic(modifiers)
            && (sd != null && !sd.getName().endsWith("Logger"))) {

         List vars = fd.getVariables();
         boolean isInit = false;
         if (vars != null) {
            Iterator it = vars.iterator();

            while (it.hasNext() && !isInit) {
               VariableDeclarator vd = it.next();
               Expression init = vd.getInit();
               boolean isValid = true;
               
               if (init instanceof MethodCallExpr) {
                  MethodCallExpr mce = (MethodCallExpr) init;
                  isValid = !(mce.getName().equals("currentTimeMillis"));
               }
               isInit = init != null && isValid;
            }
         }
         if (isInit) {
            List refs = fd.getUsages();
            if (refs != null) {
               MethodDeclaration md = null;
               Iterator it = refs.iterator();
               boolean isSingular = true;
               while (it.hasNext() && isSingular) {
                  SymbolReference sr = it.next();
                  MethodDeclaration aux = getMethod((Node) sr);
                  if (aux == null) {
                     isSingular = false;
                  } else if (md == null) {
                     md = aux;
                  } else if (md != aux) {
                     isSingular = false;
                  }
               }
               if (isSingular) {

                  MethodDeclaration aux = (MethodDeclaration) md;
                  BlockStmt block = aux.getBody();
                  List stmts = block.getStmts();

                  try {
                     FieldDeclaration fdaux = fd.clone();
                     stmts.add(0,
                           new ExpressionStmt(new VariableDeclarationExpr(fdaux.getType(), fdaux.getVariables())));
                     fd.remove();
                  } catch (CloneNotSupportedException e) {
                     throw new RuntimeException(e);
                  }
               }
            }
         }
      }
   }

   public MethodDeclaration getMethod(Node n) {
      if (n == null) {
         return null;
      }

      if (n instanceof MethodDeclaration) {
         return (MethodDeclaration) n;
      } else {
         return getMethod(n.getParentNode());
      }
   }
   
  
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy