11#include " LocationManager.h"
22#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>
75
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 );
1811 }
19- config = json::parse (s.str ());
20- validateConfig (config);
21- }
12+ };
2213
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 );
3330 }
34- json headerEntry = it.value ();
35- validateHeaderEntry (headerEntry);
3631 }
37- }
32+ };
3833
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)
6936
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)) {}
7939
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 ;
9253}
9354
9455bool LocationManager::inMainFile (const Location &location) const {
@@ -99,40 +60,36 @@ bool LocationManager::isImported(const Location &location) const {
9960 if (location.getPath ().empty ()) {
10061 return false ;
10162 }
102- json headerEntry = getHeaderEntry (location);
103- return !headerEntry.empty ();
63+ return getHeaderEntryIndex (location) != headerEntries.size ();
10464}
10565
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 ();
11977}
12078
12179std::string LocationManager::getImportedType (const Location &location,
12280 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];
12986
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 ;
13590 }
13691 }
137- return scalaObject + " ." + handleReservedWords (replaceChar (name, " " , " _" ));
92+
93+ return headerEntry.object + " ." +
94+ handleReservedWords (replaceChar (name, " " , " _" ));
13895}
0 commit comments