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 This file contains the checkers for different languages.
11 */
12 module autoformat.filetype;
13 
14 import std.array : array;
15 import std.algorithm;
16 import std.file;
17 import std.path;
18 
19 import autoformat.git;
20 import autoformat.types;
21 
22 enum filetypeCheckers = [&isC_CppFiletype, &isDFiletype, &isRustFiletype];
23 
24 immutable string[] suppressAutoformatFilenames = import("magic_suppress_autoformat_filenames.conf")
25     .splitter("\n").filter!(a => a.length > 0).array();
26 
27 bool isFiletypeSupported(AbsolutePath p) nothrow {
28     foreach (f; filetypeCheckers) {
29         if (f(p.extension)) {
30             return true;
31         }
32     }
33 
34     return false;
35 }
36 
37 bool isC_CppFiletype(string p) nothrow {
38     enum types = import("filetype_c_cpp.txt").splitter.array();
39     return types.canFind(p) != 0;
40 }
41 
42 bool isDFiletype(string p) nothrow {
43     enum types = import("filetype_d.txt").splitter.array();
44     return types.canFind(p) != 0;
45 }
46 
47 bool isRustFiletype(string p) nothrow {
48     enum types = import("filetype_rust.txt").splitter.array();
49     return types.canFind(p) != 0;
50 }
51 
52 auto isOkToFormat(AbsolutePath p) nothrow {
53     struct Result {
54         string payload;
55         bool ok;
56     }
57 
58     auto res = Result(null, true);
59 
60     if (!exists(p)) {
61         res = Result("file not found: " ~ p);
62     } else if (!isFiletypeSupported(p)) {
63         res = Result("filetype not supported: " ~ p);
64     } else {
65         string w = p;
66         while (w != "/") {
67             foreach (check; suppressAutoformatFilenames.map!(a => buildPath(w, a))) {
68                 if (exists(check)) {
69                     return Result("autoformat of '" ~ p ~ "' blocked by: " ~ check);
70                 }
71             }
72 
73             try {
74                 auto a = AbsolutePath(w);
75                 if (isGitRoot(a)) {
76                     break;
77                 }
78             } catch (Exception ex) {
79             }
80 
81             w = dirName(w);
82         }
83     }
84 
85     return res;
86 }