/cpp/src/main/java/com/google/test/metric/cpp/CppClassRepository.java

http://testability-explorer.googlecode.com/ · 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. */
  16. package com.google.test.metric.cpp;
  17. import com.google.test.metric.ClassInfo;
  18. import com.google.test.metric.ClassRepository;
  19. import com.google.test.metric.FieldInfo;
  20. import com.google.test.metric.LocalVariableInfo;
  21. import com.google.test.metric.MethodInfo;
  22. import com.google.test.metric.Type;
  23. import com.google.test.metric.Variable;
  24. import com.google.test.metric.cpp.dom.AssignmentExpression;
  25. import com.google.test.metric.cpp.dom.ClassDeclaration;
  26. import com.google.test.metric.cpp.dom.FunctionDefinition;
  27. import com.google.test.metric.cpp.dom.Name;
  28. import com.google.test.metric.cpp.dom.Node;
  29. import com.google.test.metric.cpp.dom.ReturnStatement;
  30. import com.google.test.metric.cpp.dom.TranslationUnit;
  31. import com.google.test.metric.cpp.dom.VariableDeclaration;
  32. import com.google.test.metric.cpp.dom.Visitor;
  33. import com.google.test.metric.method.op.turing.FieldAssignment;
  34. import com.google.test.metric.method.op.turing.LocalAssignment;
  35. import com.google.test.metric.method.op.turing.Operation;
  36. import com.google.test.metric.method.op.turing.ReturnOperation;
  37. import java.io.InputStream;
  38. import java.util.ArrayList;
  39. import java.util.HashMap;
  40. import java.util.List;
  41. import java.util.Map;
  42. import java.util.Stack;
  43. public class CppClassRepository implements ClassRepository {
  44. private final Map<String, ClassInfo> classes = new HashMap<String, ClassInfo>();
  45. private static class LocalVariableExtractor extends Visitor {
  46. private final List<LocalVariableInfo> variables = new ArrayList<LocalVariableInfo>();
  47. List<LocalVariableInfo> getResult() {
  48. return variables;
  49. }
  50. @Override
  51. public void visit(VariableDeclaration localVariableDeclaration) {
  52. Type variableType = CppType.fromName(localVariableDeclaration.getName(),
  53. localVariableDeclaration.isPointer());
  54. variables.add(new LocalVariableInfo(localVariableDeclaration.getName(),
  55. variableType));
  56. }
  57. }
  58. private static class OperationBuilder extends Visitor {
  59. private final List<Operation> operations = new ArrayList<Operation>();
  60. private final CppClassRepository repository;
  61. public OperationBuilder(CppClassRepository repository) {
  62. this.repository = repository;
  63. }
  64. List<Operation> getResult() {
  65. return operations;
  66. }
  67. @Override
  68. public void visit(AssignmentExpression assignmentExpression) {
  69. Node leftSide = assignmentExpression.getExpression(0);
  70. Node rightSide = assignmentExpression.getExpression(1);
  71. Variable leftVar = null;
  72. Variable rightVar = null;
  73. VariableDeclaration leftDeclaration = null;
  74. if (leftSide instanceof Name) {
  75. Name leftName = (Name) leftSide;
  76. leftDeclaration = leftName.lookupVariable(leftName.getIdentifier());
  77. leftVar = new Variable(leftDeclaration.getName(),
  78. CppType.fromName(leftDeclaration.getType()), false, false);
  79. }
  80. if (rightSide instanceof Name) {
  81. Name rightName = (Name) rightSide;
  82. VariableDeclaration declaration = rightName.lookupVariable(
  83. rightName.getIdentifier());
  84. rightVar = new Variable(declaration.getName(),
  85. CppType.fromName(declaration.getType()), false, false);
  86. }
  87. if (leftVar != null && rightVar != null) {
  88. Node leftParent = leftDeclaration.getParent();
  89. if (leftParent instanceof ClassDeclaration) {
  90. ClassInfo classInfo = repository.getClass(leftDeclaration.getName());
  91. Type fieldType = CppType.fromName(leftDeclaration.getType());
  92. FieldInfo fieldInfo = new FieldInfo(classInfo, leftDeclaration
  93. .getName(), fieldType, false, false, false);
  94. operations.add(new FieldAssignment(assignmentExpression
  95. .getLineNumber(), leftVar, fieldInfo, rightVar));
  96. } else {
  97. operations.add(new LocalAssignment(assignmentExpression
  98. .getLineNumber(), leftVar, rightVar));
  99. }
  100. }
  101. }
  102. @Override
  103. public void beginVisit(ReturnStatement returnStatement) {
  104. operations.add(new ReturnOperation(returnStatement.getLineNumber(), null));
  105. }
  106. }
  107. private class ClassInfoBuilder extends Visitor {
  108. private final Stack<ClassInfo> stack = new Stack<ClassInfo>();
  109. private final CppClassRepository repository;
  110. public ClassInfoBuilder(CppClassRepository repository) {
  111. this.repository = repository;
  112. }
  113. @Override
  114. public void beginVisit(ClassDeclaration classDeclaration) {
  115. //TODO: when the class repository is actually wired, the name of the source file should
  116. // be provided in the constructor
  117. ClassInfo classInfo = new ClassInfo(classDeclaration.getName(), false,
  118. null, new ArrayList<ClassInfo>(), "[unknown source]");
  119. classes.put(classDeclaration.getName(), classInfo);
  120. stack.push(classInfo);
  121. }
  122. @Override
  123. public void endVisit(ClassDeclaration classDeclaration) {
  124. stack.pop();
  125. }
  126. @Override
  127. public void beginVisit(FunctionDefinition functionDefinition) {
  128. LocalVariableExtractor localVariablesExtractor = new LocalVariableExtractor();
  129. functionDefinition.accept(localVariablesExtractor);
  130. OperationBuilder operationBuilder = new OperationBuilder(repository);
  131. functionDefinition.accept(operationBuilder);
  132. ClassInfo classInfo = stack.peek();
  133. classInfo.addMethod(new MethodInfo(
  134. classInfo,
  135. functionDefinition.getName(),
  136. functionDefinition.getLine(),
  137. null,
  138. functionDefinition.getParameters(),
  139. localVariablesExtractor.getResult(),
  140. functionDefinition.getVisibility(),
  141. operationBuilder.getResult(),
  142. false,
  143. false, new ArrayList<Integer>()));
  144. }
  145. }
  146. public ClassInfo getClass(String clazzName) {
  147. return classes.get(clazzName);
  148. }
  149. public void addClass(ClassInfo classInfo) {
  150. classes.put(classInfo.getName(), classInfo);
  151. }
  152. void parse(InputStream in) throws Exception {
  153. TranslationUnit unit = new Parser().parse(in);
  154. ClassInfoBuilder builder = new ClassInfoBuilder(this);
  155. unit.accept(builder);
  156. }
  157. public void parse(String in) throws Exception {
  158. TranslationUnit unit = new Parser().parse(in);
  159. ClassInfoBuilder builder = new ClassInfoBuilder(this);
  160. unit.accept(builder);
  161. }
  162. }