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 }