1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 */ 10 module dextool.plugin.mutate.backend.interface_; 11 12 import std.exception : collectException; 13 import std.stdio : File; 14 import logger = std.experimental.logger; 15 16 public import blob_model : Blob; 17 18 import dextool.type : AbsolutePath; 19 20 @safe: 21 22 /** Validate source code locations for analyze and mutation. 23 */ 24 interface ValidateLoc { 25 /// Returns: the root directory that files to be mutated must reside inside 26 AbsolutePath getOutputDir() nothrow; 27 28 /// Returns: if a path should be analyzed for mutation points. 29 bool shouldAnalyze(AbsolutePath p); 30 31 /// ditto 32 bool shouldAnalyze(string p); 33 34 /// Returns: if a mutant are allowed to be written to this path. 35 bool shouldMutate(AbsolutePath p); 36 } 37 38 /** Filesystem I/O from the backend. 39 * 40 * TODO: rename outputDir to workdir. It is the terminology used in git. 41 * 42 * The implementation of the interface shall: 43 * ensure all SafeOutput objects are inside the _output directory_. 44 * 45 * The design is intended to create a clear distinction between output and 46 * input. It is to make it easier to do code review and reason about where 47 * filesystem output is created. 48 */ 49 interface FilesysIO { 50 import dextool.type : Path; 51 import std.stdio : File; 52 53 // these are here so backend do not need to import std.stdio which makes it 54 // easier to review. 55 File getDevNull(); 56 File getStdin(); 57 58 /// Convert a path to be relative to the root of the filesystem. 59 Path toRelativeRoot(Path p); 60 61 /// File output is restricted to this directory 62 AbsolutePath getOutputDir() nothrow; 63 64 /// 65 SafeOutput makeOutput(AbsolutePath p); 66 67 /// 68 Blob makeInput(AbsolutePath p); 69 70 protected: 71 void putFile(AbsolutePath fname, const(ubyte)[] data); 72 } 73 74 struct SafeOutput { 75 import std.array : Appender; 76 77 private AbsolutePath fname; 78 private FilesysIO fsys; 79 private Appender!(ubyte[]) buf; 80 private bool is_open; 81 82 @disable this(this); 83 84 this(AbsolutePath fname, FilesysIO fsys) { 85 this.fname = fname; 86 this.fsys = fsys; 87 this.is_open = true; 88 } 89 90 ~this() { 91 close(); 92 } 93 94 // trusted: the data is copied therefore it is safe to cast away const. 95 void write(T)(inout T data) @trusted if (!is(T == ubyte[])) { 96 buf.put(cast(ubyte[]) data); 97 } 98 99 void write(T)(inout T data) if (is(T == ubyte[])) { 100 buf.put(data); 101 } 102 103 void write(Blob b) { 104 buf.put(b.content); 105 } 106 107 void close() { 108 if (is_open) { 109 fsys.putFile(fname, buf.data); 110 buf.clear; 111 } 112 is_open = false; 113 } 114 }