1
1
#include " LocationManager.h"
2
2
#include " ../Utils.h"
3
- #include " Enum.h"
4
- #include " Struct.h"
5
- #include < fstream>
6
- #include < stdexcept>
3
+ #include < llvm/Support/MemoryBuffer.h>
4
+ #include < llvm/Support/YAMLTraits.h>
7
5
8
- LocationManager::LocationManager (std::string mainHeaderPath)
9
- : mainHeaderPath(std::move(mainHeaderPath)) {}
10
-
11
- void LocationManager::loadConfig (const std::string &path) {
12
- std::string realPath = getRealPath (path.c_str ());
13
-
14
- std::stringstream s;
15
- std::ifstream input (realPath);
16
- for (std::string line; getline (input, line);) {
17
- s << line;
6
+ template <> struct llvm ::yaml::MappingTraits<HeaderEntry> {
7
+ static void mapping (llvm::yaml::IO &io, HeaderEntry &headerEntry) {
8
+ io.mapRequired (" path" , headerEntry.path );
9
+ io.mapRequired (" object" , headerEntry.object );
10
+ io.mapOptional (" names" , headerEntry.names );
18
11
}
19
- config = json::parse (s.str ());
20
- validateConfig (config);
21
- }
12
+ };
22
13
23
- void LocationManager::validateConfig (const json &config) const {
24
- if (!config.is_object ()) {
25
- throw std::invalid_argument (
26
- " Invalid configuration. Configuration should be an object." );
27
- }
28
- for (auto it = config.begin (); it != config.end (); ++it) {
29
- std::string headerName = it.key ();
30
- if (headerName.empty ()) {
31
- throw std::invalid_argument (" Invalid configuration. Header name "
32
- " should not be an empty string." );
14
+ template <> struct llvm ::yaml::MappingTraits<HeaderEntryName> {
15
+ static void mapping (llvm::yaml::IO &io, HeaderEntryName &headerEntryName) {
16
+ // Dynamically look up the available keys when only one key is given.
17
+ //
18
+ // ```yaml
19
+ // - struct point: Point
20
+ // ```
21
+ if (io.keys ().size () == 1 ) {
22
+ for (auto key : io.keys ()) {
23
+ headerEntryName.original = key;
24
+ io.mapRequired (headerEntryName.original .c_str (),
25
+ headerEntryName.target );
26
+ }
27
+ } else {
28
+ io.mapRequired (" original" , headerEntryName.original );
29
+ io.mapRequired (" target" , headerEntryName.target );
33
30
}
34
- json headerEntry = it.value ();
35
- validateHeaderEntry (headerEntry);
36
31
}
37
- }
32
+ };
38
33
39
- void LocationManager::validateHeaderEntry (const json &headerEntry) const {
40
- if (headerEntry.is_string ()) {
41
- std::string object = headerEntry.get <std::string>();
42
- if (object.empty ()) {
43
- throw std::invalid_argument (" Invalid configuration. Each header "
44
- " entry should contain non-empty "
45
- " value." );
46
- }
47
- } else if (headerEntry.is_object ()) {
48
- std::unordered_set<std::string> headerKeys = {" object" , " names" };
49
- validateKeys (headerEntry, headerKeys);
50
- if (headerEntry.find (" object" ) == headerEntry.end ()) {
51
- throw std::invalid_argument (" Invalid configuration. Header entry "
52
- " that is represented as an object "
53
- " should contain 'object' property." );
54
- }
55
- json object = headerEntry[" object" ];
56
- if (!object.is_string () || object.get <std::string>().empty ()) {
57
- throw std::invalid_argument (" Invalid configuration. 'object' "
58
- " property should be a not empty "
59
- " string." );
60
- }
61
- if (headerEntry.find (" name" ) != headerEntry.end ()) {
62
- validateNames (headerEntry[" names" ]);
63
- }
64
- } else {
65
- throw std::invalid_argument (" Invalid configuration. Header entry "
66
- " should be a string or an object." );
67
- }
68
- }
34
+ LLVM_YAML_IS_SEQUENCE_VECTOR (HeaderEntry)
35
+ LLVM_YAML_IS_SEQUENCE_VECTOR(HeaderEntryName)
69
36
70
- void LocationManager::validateKeys (
71
- const json &object, const std::unordered_set<std::string> &keys) const {
72
- for (auto it = object.begin (); it != object.end (); ++it) {
73
- if (keys.find (it.key ()) == keys.end ()) {
74
- throw std::invalid_argument (
75
- " Invalid configuration. Unknown key: '" + it.key () + " '." );
76
- }
77
- }
78
- }
37
+ LocationManager::LocationManager(std::string mainHeaderPath)
38
+ : headerEntries(), mainHeaderPath(std::move(mainHeaderPath)) {}
79
39
80
- void LocationManager::validateNames (const json &names) const {
81
- if (!names.is_object ()) {
82
- throw std::invalid_argument (" Invalid configuration. Library property "
83
- " 'names' should be an object." );
84
- }
85
- for (auto it = names.begin (); it != names.end (); ++it) {
86
- if (!it.value ().is_string ()) {
87
- throw std::invalid_argument (
88
- " Invalid configuration. property 'names'"
89
- " should contain only string values." );
90
- }
91
- }
40
+ bool LocationManager::loadConfig (const std::string &path) {
41
+ llvm::SmallString<4096 > realPath;
42
+ if (llvm::sys::fs::real_path (path, realPath))
43
+ return false ;
44
+
45
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb =
46
+ llvm::MemoryBuffer::getFile (realPath);
47
+ if (!mb)
48
+ return false ;
49
+
50
+ llvm::yaml::Input input (mb->get ()->getBuffer ());
51
+ input >> headerEntries;
52
+ return true ;
92
53
}
93
54
94
55
bool LocationManager::inMainFile (const Location &location) const {
@@ -99,40 +60,36 @@ bool LocationManager::isImported(const Location &location) const {
99
60
if (location.getPath ().empty ()) {
100
61
return false ;
101
62
}
102
- json headerEntry = getHeaderEntry (location);
103
- return !headerEntry.empty ();
63
+ return getHeaderEntryIndex (location) != headerEntries.size ();
104
64
}
105
65
106
- json LocationManager::getHeaderEntry (const Location &location) const {
107
- for (auto it = config.begin (); it != config.end (); ++it) {
108
- std::string pathToHeader = it.key ();
109
- if (startsWith (pathToHeader, " /" )) {
110
- /* full path */
111
- if (location.getPath () == pathToHeader) {
112
- return it.value ();
113
- }
114
- } else if (endsWith (location.getPath (), " /" + pathToHeader)) {
115
- return it.value ();
116
- }
117
- }
118
- return json::object ();
66
+ std::vector<HeaderEntry>::size_type
67
+ LocationManager::getHeaderEntryIndex (const Location &location) const {
68
+ auto isHeader = [&](const HeaderEntry &headerEntry) {
69
+ if (startsWith (headerEntry.path , " /" ) &&
70
+ location.getPath () == headerEntry.path )
71
+ return true ;
72
+ return endsWith (location.getPath (), " /" + headerEntry.path );
73
+ };
74
+ auto it =
75
+ std::find_if (headerEntries.begin (), headerEntries.end (), isHeader);
76
+ return it - headerEntries.begin ();
119
77
}
120
78
121
79
std::string LocationManager::getImportedType (const Location &location,
122
80
const std::string &name) const {
123
- json headerEntry = getHeaderEntry (location);
124
- if (headerEntry.is_string ()) {
125
- return headerEntry.get <std::string>() + " ." +
126
- handleReservedWords (replaceChar (name, " " , " _" ));
127
- }
128
- std::string scalaObject = headerEntry[" object" ];
81
+ auto index = getHeaderEntryIndex (location);
82
+ if (index == headerEntries.size ())
83
+ return name;
84
+
85
+ auto headerEntry = headerEntries[index ];
129
86
130
- if (headerEntry.find (" names" ) != headerEntry.end ()) {
131
- /* name mapping */
132
- json names = headerEntry[" names" ];
133
- if (names.find (name) != names.end ()) {
134
- return scalaObject + " ." + names[name].get <std::string>();
87
+ for (auto const &headerEntryName : headerEntry.names ) {
88
+ if (headerEntryName.original == name) {
89
+ return headerEntry.object + " ." + headerEntryName.target ;
135
90
}
136
91
}
137
- return scalaObject + " ." + handleReservedWords (replaceChar (name, " " , " _" ));
92
+
93
+ return headerEntry.object + " ." +
94
+ handleReservedWords (replaceChar (name, " " , " _" ));
138
95
}
0 commit comments