/// <summary> /// Executes visits /// </summary> public void Execute(BaseVisitor visitor) { foreach (var assemblyPath in _assemblyPaths) { ProcessAssembly(assemblyPath, visitor); } visitor.LastVisit(_context); }
/// <summary> /// Executes visits to module and processes its types /// </summary> private void ProcessModule(BaseVisitor visitor, ModuleDefinition moduleDef) { _context.CurrentModuleId++; _context.CurrentPointId = 0; visitor.VisitModule(moduleDef, _context); foreach (TypeDefinition typeDef in moduleDef.Types) { ProcessType(visitor, typeDef); } }
/// <summary> /// Visits all method sequence points that /// have corresponding source code segments /// locations in pdb files /// </summary> private void ProcessMethod(BaseVisitor visitor, MethodDefinition methodDef) { var segments = _context.CodeSegmentReader.GetSegmentsByMethod(methodDef); if (segments.Count == 0) { return; } _context.SkipMethod = IsFiltered(methodDef); visitor.VisitMethod(methodDef, _context); ///Probably there is no need in sequence point enumeration ///if this method should be skipped from instrumentation... ///But still for some reason there is an "excluded" attribute defined ///for sequence point in NCover's xml... ///In case of this optimization following lines should be uncomented: //if(!_context.ShouldInstrumentCurrentMember) // return; var instructions = methodDef.Body.Instructions; var instIdx = instructions.Count - 1; foreach (var offsetPointPair in segments.OrderByDescending(pair => pair.Key)) { var pair = offsetPointPair; ///take only these sequence poins that have corresponding code segment locations if (pair.Value.StartLine == FeeFeeMarker) { continue; } ///Locate instruction by offset while (instIdx > 0 && (instructions[instIdx].Offset > pair.Key || instructions[instIdx].Offset == 0)) { instIdx--; } var instruction = instructions[instIdx]; if (instruction.Offset != pair.Key) { continue; } _context.CurrentPointId++; visitor.VisitMethodPoint(instruction, pair.Value, _context); } visitor.LastVisitMethod(methodDef, _context); }
/// <summary> /// Executes visits to assembly and processes its modules /// </summary> private void ProcessAssembly(string assemblyPath, BaseVisitor visitor) { _context.SetCurrentAssembly(assemblyPath); var assemblyDef = AssemblyFactory.GetAssembly(assemblyPath); _context.SkipAssembly = IsFiltered(assemblyDef); visitor.VisitAssembly(assemblyDef, _context); foreach (ModuleDefinition moduleDef in assemblyDef.Modules) { ProcessModule(visitor, moduleDef); } visitor.LastVisitAssembly(assemblyDef, _context); }
/// <summary> /// Executes visits to type and processes its methods /// </summary> private void ProcessType(BaseVisitor visitor, TypeDefinition typeDef) { _context.SkipType = IsFiltered(typeDef); visitor.VisitType(typeDef, _context); ///Take all methods and constructors definitions var methods = typeDef.Methods.Cast <MethodDefinition>().Union(typeDef.Constructors.Cast <MethodDefinition>()); foreach (var methodDef in methods) { if (methodDef.IsAbstract || methodDef.IsRuntime || methodDef.IsPInvokeImpl) { continue; } ProcessMethod(visitor, methodDef); } }