001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
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 AsmClass targetClass = asmClassProvider.getClass(owner, DETAIL_LEVEL.NOTHING);
051 AsmMethod targetMethod = targetClass.getMethodOrCreateIt(methodName + methodDescription);
052 method.addEdge(new AsmEdge(method, targetMethod, SourceCodeEdgeUsage.CALLS_METHOD, lineNumber));
053 emptyMethod = false;
054 }
055
056 public void visitTryCatchBlock(Label start, Label end, Label handler, String exception) {
057 if (exception != null) {
058 AsmClass exceptionClass = asmClassProvider.getClass(exception, DETAIL_LEVEL.NOTHING);
059 method.addEdge(new AsmEdge(method, exceptionClass, SourceCodeEdgeUsage.USES, lineNumber));
060 }
061 emptyMethod = false;
062 }
063
064 public void visitTypeInsn(int opcode, String internalName) {
065 AsmClass usedClass = asmClassProvider.getClass(internalName, DETAIL_LEVEL.NOTHING);
066 method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber));
067 emptyMethod = false;
068 }
069
070 public void visitLineNumber(final int line, final Label start) {
071 lineNumber = line;
072 }
073
074 public void visitEnd() {
075 method.setEmpty(emptyMethod);
076 }
077
078 public void visitIincInsn(int var, int increment) {
079 emptyMethod = false;
080 }
081
082 public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
083 emptyMethod = false;
084 }
085
086 public void visitInsn(int opcode) {
087 if (opcode != Opcodes.RETURN) {
088 emptyMethod = false;
089 }
090 }
091
092 public void visitIntInsn(int opcode, int operand) {
093 emptyMethod = false;
094 }
095
096 public void visitJumpInsn(int opcode, Label label) {
097 emptyMethod = false;
098 }
099
100 public void visitLdcInsn(Object cst) {
101 if (cst instanceof Type) {
102 Type type = (Type) cst;
103 AsmClass usedClass = asmClassProvider.getClass(type.getInternalName(), DETAIL_LEVEL.NOTHING);
104 method.addEdge(new AsmEdge(method, usedClass, SourceCodeEdgeUsage.USES, lineNumber));
105 }
106 emptyMethod = false;
107 }
108
109 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
110 emptyMethod = false;
111 }
112
113 public void visitMultiANewArrayInsn(String desc, int dims) {
114 emptyMethod = false;
115 }
116
117 public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
118 emptyMethod = false;
119 }
120
121 public void visitVarInsn(int opcode, int var) {
122 emptyMethod = false;
123 }
124 }