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    }