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

org.sonar.java.signature.MethodSignatureScanner Maven / Gradle / Ivy

The newest version!
/*
 * SonarQube Java
 * Copyright (C) 2012 SonarSource
 * [email protected]
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package org.sonar.java.signature;

import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import org.sonar.java.ast.api.JavaKeyword;
import org.sonar.plugins.java.api.tree.ArrayTypeTree;
import org.sonar.plugins.java.api.tree.IdentifierTree;
import org.sonar.plugins.java.api.tree.MemberSelectExpressionTree;
import org.sonar.plugins.java.api.tree.MethodTree;
import org.sonar.plugins.java.api.tree.ParameterizedTypeTree;
import org.sonar.plugins.java.api.tree.PrimitiveTypeTree;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.VariableTree;

import java.util.List;

public final class MethodSignatureScanner {

  private final String bytecodeMethodSignature;
  private final MethodTree methodTree;

  private static final BiMap JAVA_TYPE_MAPPING = HashBiMap.create();

  static {
    JAVA_TYPE_MAPPING.put(JavaKeyword.BYTE.getValue(), JvmJavaType.B);
    JAVA_TYPE_MAPPING.put(JavaKeyword.CHAR.getValue(), JvmJavaType.C);
    JAVA_TYPE_MAPPING.put(JavaKeyword.SHORT.getValue(), JvmJavaType.S);
    JAVA_TYPE_MAPPING.put(JavaKeyword.INT.getValue(), JvmJavaType.I);
    JAVA_TYPE_MAPPING.put(JavaKeyword.LONG.getValue(), JvmJavaType.J);
    JAVA_TYPE_MAPPING.put(JavaKeyword.BOOLEAN.getValue(), JvmJavaType.Z);
    JAVA_TYPE_MAPPING.put(JavaKeyword.FLOAT.getValue(), JvmJavaType.F);
    JAVA_TYPE_MAPPING.put(JavaKeyword.DOUBLE.getValue(), JvmJavaType.D);
    JAVA_TYPE_MAPPING.put(JavaKeyword.VOID.getValue(), JvmJavaType.V);
  }

  public MethodSignatureScanner(MethodTree methodTree) {
    this.methodTree = methodTree;
    bytecodeMethodSignature = null;
  }

  public static MethodSignature scan(MethodTree methodTree) {
    MethodSignatureScanner scanner = new MethodSignatureScanner(methodTree);
    return scanner.scanTree();
  }

  public static String getReadableType(JvmJavaType jvmJavaType) {
    return JAVA_TYPE_MAPPING.inverse().get(jvmJavaType);
  }

  private MethodSignature scanTree() {
    String name = methodTree.simpleName().name();
    Parameter returnTypeParam;
    if (methodTree.is(Tree.Kind.CONSTRUCTOR)) {
      name = "";
      returnTypeParam = new Parameter(JvmJavaType.V, false);
    } else {
      returnTypeParam = getParameter(methodTree.returnType());
    }

    List argumentTypes = Lists.newArrayList();
    for (VariableTree variableTree : methodTree.parameters()) {
      argumentTypes.add(getParameter(variableTree.type()));
    }

    return new MethodSignature(name, returnTypeParam, argumentTypes);
  }

  private Parameter getParameter(Tree typeTree) {
    Parameter parameter;
    boolean isArray = false;
    Tree type = typeTree;
    if (type.is(Tree.Kind.ARRAY_TYPE)) {
      isArray = true;
      while (type.is(Tree.Kind.ARRAY_TYPE)) {
        type = ((ArrayTypeTree) type).type();
      }
    }
    JvmJavaType jvmType = jvmJavaTypeOf(type);
    if (jvmType.equals(JvmJavaType.L)) {
      parameter = new Parameter(getTypeName(type), isArray);
    } else {
      parameter = new Parameter(jvmType, isArray);
    }
    return parameter;
  }

  private String getTypeName(Tree typeTree) {
    if (typeTree.is(Tree.Kind.IDENTIFIER)) {
      return ((IdentifierTree) typeTree).name();
    } else if (typeTree.is(Tree.Kind.MEMBER_SELECT)) {
      return ((MemberSelectExpressionTree) typeTree).identifier().name();
    } else if (typeTree.is(Tree.Kind.PARAMETERIZED_TYPE)) {
      return getTypeName(((ParameterizedTypeTree) typeTree).type());
    }
    return "";
  }

  private JvmJavaType jvmJavaTypeOf(Tree type) {
    if (type.is(Tree.Kind.PRIMITIVE_TYPE)) {
      return JAVA_TYPE_MAPPING.get(((PrimitiveTypeTree) type).keyword().text());
    }
    return JvmJavaType.L;
  }

  private MethodSignatureScanner(String bytecodeMethodSignature) {
    this.bytecodeMethodSignature = bytecodeMethodSignature;
    methodTree = null;
  }

  public static MethodSignature scan(String bytecodeMethodSignature) {
    Preconditions.checkNotNull(bytecodeMethodSignature);
    MethodSignatureScanner scanner = new MethodSignatureScanner(bytecodeMethodSignature);
    return scanner.scan();
  }

  private MethodSignature scan() {
    int leftBracketIndex = bytecodeMethodSignature.indexOf('(');
    int rightBracketIndex = bytecodeMethodSignature.indexOf(')');
    String methodName = bytecodeMethodSignature.substring(0, leftBracketIndex);
    Parameter returnType = ParameterSignatureScanner.scan(bytecodeMethodSignature.substring(rightBracketIndex + 1));
    List argumentTypes = ParameterSignatureScanner.scanArguments(bytecodeMethodSignature.substring(leftBracketIndex + 1,
      rightBracketIndex));
    return new MethodSignature(methodName, returnType, argumentTypes);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy