1
2
3
4
5
6 #include <cmajor/symbols/EditModuleCache.hpp>
7 #include <cmajor/symbols/GlobalFlags.hpp>
8 #include <cmajor/symbols/ModuleCache.hpp>
9 #include <soulng/util/MappedInputFile.hpp>
10 #include <soulng/util/Sha1.hpp>
11 #include <soulng/util/Unicode.hpp>
12
13 namespace cmajor { namespace symbols {
14
15 using namespace soulng::unicode;
16
17 ReadProjectFunc readProjectFunction;
18
19 void SetReadProjectFunction(ReadProjectFunc readProjectFunc)
20 {
21 readProjectFunction = readProjectFunc;
22 }
23
24 std::string MakeEditModuleKey(const std::string& projectFilePath, const std::string& backendStr, const std::string& configurationStr)
25 {
26 std::string editModuleKey = projectFilePath;
27 editModuleKey.append(":").append(backendStr).append(":").append(configurationStr);
28 return editModuleKey;
29 }
30
31 bool toolChainsRead = false;
32
33 std::unique_ptr<EditModuleCache> EditModuleCache::instance;
34
35 void EditModuleCache::Init()
36 {
37 instance.reset(new EditModuleCache());
38 }
39
40 void EditModuleCache::Done()
41 {
42 instance.reset();
43 }
44
45 EditModuleCache::EditModuleCache()
46 {
47 }
48
49 LoadEditModuleResult EditModuleCache::LoadEditModule(const std::string& projectFilePath, const std::string& backendStr, const std::string& configurationStr)
50 {
51 LoadEditModuleResult result;
52 result.ok = true;
53 result.error = std::string();
54 result.startLoading = std::chrono::steady_clock::now();
55 result.resultKind = LoadEditModuleResultKind::moduleLoaded;
56 cmajor::symbols::ResetGlobalFlags();
57 std::string projectFileContent = ReadFile(projectFilePath);
58 std::string projectFileHash = GetSha1MessageDigest(projectFileContent);
59 int index = editModules.size();
60 std::string editModuleKey = MakeEditModuleKey(projectFilePath, backendStr, configurationStr);
61 result.key = editModuleKey;
62 auto it = editModuleMap.find(editModuleKey);
63 if (it != editModuleMap.cend())
64 {
65 const std::std::pair<Module*, std::string>&moduleHashPair=it->second;
66 const std::string& prevHash = moduleHashPair.second;
67 if (prevHash == projectFileHash)
68 {
69 result.resultKind = LoadEditModuleResultKind::moduleUpToDate;
70 result.endLoading = std::chrono::steady_clock::now();
71 return result;
72 }
73 Module* module = moduleHashPair.first;
74 index = module->Index();
75 result.resultKind = LoadEditModuleResultKind::moduleReloaded;
76 }
77 if (!toolChainsRead)
78 {
79 toolChainsRead = true;
80 ReadToolChains(GetGlobalFlag(cmajor::symbols::GlobalFlags::verbose));
81 }
82 ResetToolChain();
83 sngcm::ast::BackEnd backend = sngcm::ast::BackEnd::llvm;
84 if (backendStr == "cpp")
85 {
86 backend = sngcm::ast::BackEnd::cppcm;
87 SetBackEnd(cmajor::symbols::BackEnd::cmcpp);
88 }
89 else if (backendStr == "llvm")
90 {
91 backend = sngcm::ast::BackEnd::llvm;
92 SetBackEnd(cmajor::symbols::BackEnd::llvm);
93 }
94 sngcm::ast::Config config = sngcm::ast::Config::debug;
95 if (configurationStr == "release")
96 {
97 cmajor::symbols::SetGlobalFlag(cmajor::symbols::GlobalFlags::release);
98 config = sngcm::ast::Config::release;
99 }
100 if (!readProjectFunction)
101 {
102 result.ok = false;
103 result.error = "read project function not set";
104 return result;
105 }
106 std::unique_ptr<Project> project = readProjectFunction(projectFilePath);
107 std::unique_ptr<Module> module(new Module(project->Name(), project->ModuleFilePath(), project->GetTarget()));
108 module->SetIndex(index);
109 module->SetRootModule();
110 SetRootModuleForCurrentThread(module.get());
111 module->SetLogStreamId(project->LogStreamId());
112 module->SetCurrentProjectName(project->Name());
113 module->SetCurrentToolName(U"cmccs");
114 module->SetFlag(cmajor::symbols::ModuleFlags::compiling);
115 PrepareModuleForCompilation(module.get(), project->References(), project->GetTarget());
116 module->SetSources(new Sources(project->SourceFilePaths()));
117 ParseResult parseResult = module->ParseSources();
118 result.ok = parseResult.ok;
119 result.numberOfErrors = parseResult.numberOfErrors;
120 result.synchronized = parseResult.synchronized;
121 result.error = parseResult.error;
122 result.startParsing = parseResult.start;
123 result.endParsing = parseResult.end;
124 while (index >= editModules.size())
125 {
126 editModules.push_back(std::unique_ptr<Module>());
127 }
128 editModuleMap[editModuleKey] = std::make_pair(module.get(), projectFileHash);
129 editModules[index].reset(module.release());
130 result.endLoading = std::chrono::steady_clock::now();
131 return result;
132 }
133
134 Module* EditModuleCache::GetEditModule(const std::string& projectFilePath, const std::string& backendStr, const std::string& configurationStr)
135 {
136 std::string editModuleKey = MakeEditModuleKey(projectFilePath, backendStr, configurationStr);
137 auto it = editModuleMap.find(editModuleKey);
138 if (it != editModuleMap.cend())
139 {
140 return it->second.first;
141 }
142 else
143 {
144 return nullptr;
145 }
146 }
147
148 void InitEditModuleCache()
149 {
150 EditModuleCache::Init();
151 }
152
153 void DoneEditModuleCache()
154 {
155 EditModuleCache::Done();
156 }
157
158 } }