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 */ 020 package org.sonar.java.bytecode.asm; 021 022 import org.objectweb.asm.Label; 023 import org.objectweb.asm.Opcodes; 024 import org.objectweb.asm.Type; 025 import org.objectweb.asm.commons.EmptyVisitor; 026 import org.sonar.java.bytecode.asm.AsmClassProvider.DETAIL_LEVEL; 027 import org.sonar.squid.api.SourceCodeEdgeUsage; 028 029 public 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 public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDescription) { 043 AsmClass targetClass = asmClassProvider.getClass(owner, DETAIL_LEVEL.NOTHING); 044 AsmField targetField = targetClass.getFieldOrCreateIt(fieldName); 045 method.addEdge(new AsmEdge(method, targetField, SourceCodeEdgeUsage.CALLS_FIELD, lineNumber)); 046 emptyMethod = false; 047 } 048 049 public void visitMethodInsn(int opcode, String owner, String methodName, String methodDescription) { 050 if (isNotCallToJavaArrayMethod(owner)) { 051 AsmClass targetClass = asmClassProvider.getClass(owner, DETAIL_LEVEL.STRUCTURE); 052 AsmMethod targetMethod = targetClass.getMethodOrCreateIt(methodName + methodDescription); 053 method.addEdge(new AsmEdge(method, targetMethod, SourceCodeEdgeUsage.CALLS_METHOD, lineNumber)); 054 } 055 emptyMethod = false; 056 } 057 058 private boolean isNotCallToJavaArrayMethod(String internalName) { 059 return internalName.charAt(0) != '['; 060 } 061 062 public void visitTryCatchBlock(Label start, Label end, Label handler, String exception) { 063 if (exception != null) { 064 AsmClass exceptionClass = asmClassProvider.getClass(exception, DETAIL_LEVEL.NOTHING); 065 method.addEdge(new AsmEdge(method, exceptionClass, SourceCodeEdgeUsage.USES, lineNumber)); 066 } 067 emptyMethod = false; 068 } 069 070 public void visitTypeInsn(int opcode, String internalName) { 071 AsmClass usedClass = asmClassProvider.getClass(internalName, DETAIL_LEVEL.NOTHING); 072 method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber)); 073 emptyMethod = false; 074 } 075 076 public void visitLineNumber(final int line, final Label start) { 077 lineNumber = line; 078 } 079 080 public void visitEnd() { 081 method.setEmpty(emptyMethod); 082 } 083 084 public void visitIincInsn(int var, int increment) { 085 emptyMethod = false; 086 } 087 088 public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { 089 emptyMethod = false; 090 } 091 092 public void visitInsn(int opcode) { 093 if (opcode != Opcodes.RETURN) { 094 emptyMethod = false; 095 } 096 } 097 098 public void visitIntInsn(int opcode, int operand) { 099 emptyMethod = false; 100 } 101 102 public void visitJumpInsn(int opcode, Label label) { 103 emptyMethod = false; 104 } 105 106 public void visitLdcInsn(Object cst) { 107 if (cst instanceof Type) { 108 Type type = (Type) cst; 109 AsmClass usedClass = asmClassProvider.getClass(type.getInternalName(), DETAIL_LEVEL.NOTHING); 110 method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber)); 111 } 112 emptyMethod = false; 113 } 114 115 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 116 emptyMethod = false; 117 } 118 119 public void visitMultiANewArrayInsn(String desc, int dims) { 120 emptyMethod = false; 121 } 122 123 public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { 124 emptyMethod = false; 125 } 126 127 public void visitVarInsn(int opcode, int var) { 128 emptyMethod = false; 129 } 130 }