PageRenderTime 40ms CodeModel.GetById 14ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/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 */
 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}