001/* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020package org.sonar.java.bytecode.asm; 021 022import org.objectweb.asm.Label; 023import org.objectweb.asm.Opcodes; 024import org.objectweb.asm.Type; 025import org.objectweb.asm.commons.EmptyVisitor; 026import org.sonar.java.bytecode.asm.AsmClassProvider.DETAIL_LEVEL; 027import org.sonar.squid.api.SourceCodeEdgeUsage; 028 029public class AsmMethodVisitor extends EmptyVisitor { 030 031 private AsmMethod method; 032 private AsmClassProvider asmClassProvider; 033 private int lineNumber = 0; 034 private boolean emptyMethod = true; 035 036 public AsmMethodVisitor(AsmMethod method, AsmClassProvider asmClassProvider) { 037 this.method = method; 038 this.asmClassProvider = asmClassProvider; 039 emptyMethod = true; 040 } 041 042 @Override 043 public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDescription) { 044 AsmClass targetClass = asmClassProvider.getClass(owner, DETAIL_LEVEL.NOTHING); 045 AsmField targetField = targetClass.getFieldOrCreateIt(fieldName); 046 method.addEdge(new AsmEdge(method, targetField, SourceCodeEdgeUsage.CALLS_FIELD, lineNumber)); 047 emptyMethod = false; 048 } 049 050 @Override 051 public void visitMethodInsn(int opcode, String owner, String methodName, String methodDescription) { 052 if (isNotCallToJavaArrayMethod(owner)) { 053 AsmClass targetClass = asmClassProvider.getClass(owner, DETAIL_LEVEL.STRUCTURE); 054 AsmMethod targetMethod = targetClass.getMethodOrCreateIt(methodName + methodDescription); 055 method.addEdge(new AsmEdge(method, targetMethod, SourceCodeEdgeUsage.CALLS_METHOD, lineNumber)); 056 } 057 emptyMethod = false; 058 } 059 060 private boolean isNotCallToJavaArrayMethod(String internalName) { 061 return internalName.charAt(0) != '['; 062 } 063 064 @Override 065 public void visitTryCatchBlock(Label start, Label end, Label handler, String exception) { 066 if (exception != null) { 067 AsmClass exceptionClass = asmClassProvider.getClass(exception, DETAIL_LEVEL.NOTHING); 068 method.addEdge(new AsmEdge(method, exceptionClass, SourceCodeEdgeUsage.USES, lineNumber)); 069 } 070 emptyMethod = false; 071 } 072 073 @Override 074 public void visitTypeInsn(int opcode, String internalName) { 075 AsmClass usedClass = asmClassProvider.getClass(internalName, DETAIL_LEVEL.NOTHING); 076 method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber)); 077 emptyMethod = false; 078 } 079 080 @Override 081 public void visitLineNumber(final int line, final Label start) { 082 lineNumber = line; 083 } 084 085 @Override 086 public void visitEnd() { 087 method.setEmpty(emptyMethod); 088 } 089 090 @Override 091 public void visitIincInsn(int var, int increment) { 092 emptyMethod = false; 093 } 094 095 @Override 096 public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { 097 emptyMethod = false; 098 } 099 100 @Override 101 public void visitInsn(int opcode) { 102 if (opcode != Opcodes.RETURN) { 103 emptyMethod = false; 104 } 105 } 106 107 @Override 108 public void visitIntInsn(int opcode, int operand) { 109 emptyMethod = false; 110 } 111 112 @Override 113 public void visitJumpInsn(int opcode, Label label) { 114 emptyMethod = false; 115 } 116 117 @Override 118 public void visitLdcInsn(Object cst) { 119 if (cst instanceof Type) { 120 Type type = (Type) cst; 121 AsmClass usedClass = asmClassProvider.getClass(type.getInternalName(), DETAIL_LEVEL.NOTHING); 122 method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber)); 123 } 124 emptyMethod = false; 125 } 126 127 @Override 128 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 129 emptyMethod = false; 130 } 131 132 @Override 133 public void visitMultiANewArrayInsn(String desc, int dims) { 134 emptyMethod = false; 135 } 136 137 @Override 138 public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { 139 emptyMethod = false; 140 } 141 142 @Override 143 public void visitVarInsn(int opcode, int var) { 144 emptyMethod = false; 145 } 146}