/cpp/src/main/java/com/google/test/metric/cpp/CppClassRepository.java
Java | 187 lines | 145 code | 25 blank | 17 comment | 8 complexity | 49b47054cc72d10a66cee164ee2ff9f5 MD5 | raw file
1/* 2 * Copyright 2008 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package com.google.test.metric.cpp; 17 18import com.google.test.metric.ClassInfo; 19import com.google.test.metric.ClassRepository; 20import com.google.test.metric.FieldInfo; 21import com.google.test.metric.LocalVariableInfo; 22import com.google.test.metric.MethodInfo; 23import com.google.test.metric.Type; 24import com.google.test.metric.Variable; 25import com.google.test.metric.cpp.dom.AssignmentExpression; 26import com.google.test.metric.cpp.dom.ClassDeclaration; 27import com.google.test.metric.cpp.dom.FunctionDefinition; 28import com.google.test.metric.cpp.dom.Name; 29import com.google.test.metric.cpp.dom.Node; 30import com.google.test.metric.cpp.dom.ReturnStatement; 31import com.google.test.metric.cpp.dom.TranslationUnit; 32import com.google.test.metric.cpp.dom.VariableDeclaration; 33import com.google.test.metric.cpp.dom.Visitor; 34import com.google.test.metric.method.op.turing.FieldAssignment; 35import com.google.test.metric.method.op.turing.LocalAssignment; 36import com.google.test.metric.method.op.turing.Operation; 37import com.google.test.metric.method.op.turing.ReturnOperation; 38 39import java.io.InputStream; 40import java.util.ArrayList; 41import java.util.HashMap; 42import java.util.List; 43import java.util.Map; 44import java.util.Stack; 45 46public class CppClassRepository implements ClassRepository { 47 48 private final Map<String, ClassInfo> classes = new HashMap<String, ClassInfo>(); 49 50 private static class LocalVariableExtractor extends Visitor { 51 52 private final List<LocalVariableInfo> variables = new ArrayList<LocalVariableInfo>(); 53 54 List<LocalVariableInfo> getResult() { 55 return variables; 56 } 57 58 @Override 59 public void visit(VariableDeclaration localVariableDeclaration) { 60 Type variableType = CppType.fromName(localVariableDeclaration.getName(), 61 localVariableDeclaration.isPointer()); 62 variables.add(new LocalVariableInfo(localVariableDeclaration.getName(), 63 variableType)); 64 } 65 } 66 67 private static class OperationBuilder extends Visitor { 68 69 private final List<Operation> operations = new ArrayList<Operation>(); 70 private final CppClassRepository repository; 71 72 public OperationBuilder(CppClassRepository repository) { 73 this.repository = repository; 74 } 75 76 List<Operation> getResult() { 77 return operations; 78 } 79 80 @Override 81 public void visit(AssignmentExpression assignmentExpression) { 82 Node leftSide = assignmentExpression.getExpression(0); 83 Node rightSide = assignmentExpression.getExpression(1); 84 Variable leftVar = null; 85 Variable rightVar = null; 86 VariableDeclaration leftDeclaration = null; 87 if (leftSide instanceof Name) { 88 Name leftName = (Name) leftSide; 89 leftDeclaration = leftName.lookupVariable(leftName.getIdentifier()); 90 leftVar = new Variable(leftDeclaration.getName(), 91 CppType.fromName(leftDeclaration.getType()), false, false); 92 } 93 if (rightSide instanceof Name) { 94 Name rightName = (Name) rightSide; 95 VariableDeclaration declaration = rightName.lookupVariable( 96 rightName.getIdentifier()); 97 rightVar = new Variable(declaration.getName(), 98 CppType.fromName(declaration.getType()), false, false); 99 } 100 if (leftVar != null && rightVar != null) { 101 Node leftParent = leftDeclaration.getParent(); 102 if (leftParent instanceof ClassDeclaration) { 103 ClassInfo classInfo = repository.getClass(leftDeclaration.getName()); 104 Type fieldType = CppType.fromName(leftDeclaration.getType()); 105 FieldInfo fieldInfo = new FieldInfo(classInfo, leftDeclaration 106 .getName(), fieldType, false, false, false); 107 operations.add(new FieldAssignment(assignmentExpression 108 .getLineNumber(), leftVar, fieldInfo, rightVar)); 109 } else { 110 operations.add(new LocalAssignment(assignmentExpression 111 .getLineNumber(), leftVar, rightVar)); 112 } 113 } 114 } 115 116 @Override 117 public void beginVisit(ReturnStatement returnStatement) { 118 operations.add(new ReturnOperation(returnStatement.getLineNumber(), null)); 119 } 120 } 121 122 private class ClassInfoBuilder extends Visitor { 123 124 private final Stack<ClassInfo> stack = new Stack<ClassInfo>(); 125 private final CppClassRepository repository; 126 127 public ClassInfoBuilder(CppClassRepository repository) { 128 this.repository = repository; 129 } 130 131 @Override 132 public void beginVisit(ClassDeclaration classDeclaration) { 133 //TODO: when the class repository is actually wired, the name of the source file should 134 // be provided in the constructor 135 ClassInfo classInfo = new ClassInfo(classDeclaration.getName(), false, 136 null, new ArrayList<ClassInfo>(), "[unknown source]"); 137 classes.put(classDeclaration.getName(), classInfo); 138 stack.push(classInfo); 139 } 140 141 @Override 142 public void endVisit(ClassDeclaration classDeclaration) { 143 stack.pop(); 144 } 145 146 @Override 147 public void beginVisit(FunctionDefinition functionDefinition) { 148 LocalVariableExtractor localVariablesExtractor = new LocalVariableExtractor(); 149 functionDefinition.accept(localVariablesExtractor); 150 OperationBuilder operationBuilder = new OperationBuilder(repository); 151 functionDefinition.accept(operationBuilder); 152 153 ClassInfo classInfo = stack.peek(); 154 classInfo.addMethod(new MethodInfo( 155 classInfo, 156 functionDefinition.getName(), 157 functionDefinition.getLine(), 158 null, 159 functionDefinition.getParameters(), 160 localVariablesExtractor.getResult(), 161 functionDefinition.getVisibility(), 162 operationBuilder.getResult(), 163 false, 164 false, new ArrayList<Integer>())); 165 } 166 } 167 168 public ClassInfo getClass(String clazzName) { 169 return classes.get(clazzName); 170 } 171 172 public void addClass(ClassInfo classInfo) { 173 classes.put(classInfo.getName(), classInfo); 174 } 175 176 void parse(InputStream in) throws Exception { 177 TranslationUnit unit = new Parser().parse(in); 178 ClassInfoBuilder builder = new ClassInfoBuilder(this); 179 unit.accept(builder); 180 } 181 182 public void parse(String in) throws Exception { 183 TranslationUnit unit = new Parser().parse(in); 184 ClassInfoBuilder builder = new ClassInfoBuilder(this); 185 unit.accept(builder); 186 } 187}