Skip to content

Commit 07cc489

Browse files
committed
WIP
1 parent 6eac0a2 commit 07cc489

4 files changed

Lines changed: 142 additions & 25 deletions

File tree

test/generate_test_stubs.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,20 @@ std::pair<bool, std::string> generate_stub(const fs::path &wit_file,
381381

382382
if (status != 0)
383383
{
384-
std::string error_msg = output.empty() ? "Unknown error" : output;
384+
std::string error_msg;
385+
if (output.empty())
386+
{
387+
error_msg = "Process exited with code " + std::to_string(status);
388+
// Common Windows exit codes
389+
if (status == -1073741819 || status == 3221225477) // 0xC0000005 = Access violation
390+
{
391+
error_msg += " (segmentation fault/access violation)";
392+
}
393+
}
394+
else
395+
{
396+
error_msg = output;
397+
}
385398
return {false, error_msg};
386399
}
387400

@@ -717,10 +730,7 @@ int main(int argc, char *argv[])
717730
for (const auto &[file, error] : failures)
718731
{
719732
std::cout << " - " << file << std::endl;
720-
if (verbose)
721-
{
722-
std::cout << " Error: " << error << std::endl;
723-
}
733+
std::cout << " Error: " << error << std::endl;
724734
}
725735
}
726736

tools/wit-codegen/package_registry.cpp

Lines changed: 117 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <algorithm>
44
#include <regex>
55
#include <sstream>
6+
#include <fstream>
67

78
// PackageId implementation
89

@@ -124,33 +125,56 @@ bool PackageRegistry::load_package(const std::filesystem::path &path)
124125
// Parse the WIT file
125126
auto parse_result = WitGrammarParser::parse(path.string());
126127

127-
// Skip if no package name defined (these are interface-only files that will be
128-
// loaded as part of their parent package)
128+
// If no package name defined, try to infer it from directory structure or sibling files
129+
PackageId package_id_val;
129130
if (parse_result.packageName.empty())
130131
{
131-
return true; // Not an error - just skip interface-only files
132+
auto inferred_id = infer_package_from_path(path);
133+
if (!inferred_id)
134+
{
135+
// Can't infer package - skip this file
136+
return true; // Not an error, just skip
137+
}
138+
package_id_val = *inferred_id;
132139
}
133-
134-
// Parse package ID from package name
135-
auto package_id = PackageId::parse(parse_result.packageName);
136-
if (!package_id)
140+
else
137141
{
138-
return false;
142+
// Parse package ID from package name
143+
auto package_id = PackageId::parse(parse_result.packageName);
144+
if (!package_id)
145+
{
146+
return false;
147+
}
148+
package_id_val = *package_id;
139149
}
140150

141-
// Create package
142-
auto package = std::make_unique<WitPackage>();
143-
package->id = *package_id;
144-
package->source_path = path;
151+
// Check if package already exists in registry
152+
auto *existing_package = get_package(package_id_val);
145153

146-
// Add all interfaces
147-
for (const auto &interface : parse_result.interfaces)
154+
if (existing_package)
148155
{
149-
package->add_interface(interface);
156+
// Package already exists - merge interfaces into it
157+
for (const auto &interface : parse_result.interfaces)
158+
{
159+
existing_package->add_interface(interface);
160+
}
161+
}
162+
else
163+
{
164+
// Create new package
165+
auto package = std::make_unique<WitPackage>();
166+
package->id = package_id_val;
167+
package->source_path = path;
168+
169+
// Add all interfaces
170+
for (const auto &interface : parse_result.interfaces)
171+
{
172+
package->add_interface(interface);
173+
}
174+
175+
// Add to registry
176+
add_package(std::move(package));
150177
}
151-
152-
// Add to registry
153-
add_package(std::move(package));
154178

155179
return true;
156180
}
@@ -161,6 +185,81 @@ bool PackageRegistry::load_package(const std::filesystem::path &path)
161185
}
162186
}
163187

188+
std::optional<PackageId> PackageRegistry::infer_package_from_path(const std::filesystem::path &path)
189+
{
190+
// Check sibling files in the same directory for package declarations
191+
auto parent_dir = path.parent_path();
192+
193+
try
194+
{
195+
for (const auto &entry : std::filesystem::directory_iterator(parent_dir))
196+
{
197+
if (entry.is_regular_file() &&
198+
entry.path().extension() == ".wit" &&
199+
entry.path() != path)
200+
{
201+
try
202+
{
203+
// Read first 1KB of the file to check for package declaration
204+
// This avoids full parsing which could cause issues
205+
std::ifstream file(entry.path());
206+
if (!file.is_open())
207+
continue;
208+
209+
std::string content;
210+
std::string line;
211+
size_t bytes_read = 0;
212+
const size_t MAX_BYTES = 1024;
213+
214+
while (std::getline(file, line) && bytes_read < MAX_BYTES)
215+
{
216+
bytes_read += line.size() + 1;
217+
content += line + "\n";
218+
219+
// Look for "package namespace:name@version;" pattern
220+
size_t package_pos = line.find("package");
221+
if (package_pos != std::string::npos)
222+
{
223+
// Extract the package name
224+
size_t start = package_pos + 7; // After "package"
225+
// Skip whitespace
226+
while (start < line.size() && std::isspace(line[start]))
227+
start++;
228+
229+
// Find the semicolon
230+
size_t end = line.find(';', start);
231+
if (end != std::string::npos)
232+
{
233+
std::string package_spec = line.substr(start, end - start);
234+
// Trim trailing whitespace
235+
while (!package_spec.empty() && std::isspace(package_spec.back()))
236+
package_spec.pop_back();
237+
238+
auto package_id = PackageId::parse(package_spec);
239+
if (package_id)
240+
{
241+
return package_id;
242+
}
243+
}
244+
}
245+
}
246+
}
247+
catch (...)
248+
{
249+
// Ignore errors reading sibling files
250+
continue;
251+
}
252+
}
253+
}
254+
}
255+
catch (...)
256+
{
257+
// Directory iteration error
258+
}
259+
260+
return std::nullopt;
261+
}
262+
164263
WitPackage *PackageRegistry::get_package(const PackageId &id)
165264
{
166265
auto key = id.to_string();

tools/wit-codegen/package_registry.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ class PackageRegistry
137137
*/
138138
void clear();
139139

140+
/**
141+
* Infer package ID from directory structure or sibling files
142+
* Used when loading files without package declarations
143+
* @param path Path to the WIT file
144+
* @return Package ID if inferrable, nullopt otherwise
145+
*/
146+
std::optional<PackageId> infer_package_from_path(const std::filesystem::path &path);
147+
140148
private:
141149
std::vector<std::unique_ptr<WitPackage>> packages_;
142150
std::map<std::string, WitPackage *> package_map_; // "namespace:package@version" -> package

tools/wit-codegen/wit-codegen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
102102
// 3. Load all dependencies first
103103
for (const auto &dep_file : dep_files)
104104
{
105-
std::cout << "Loading dependency: " << dep_file << "\n";
105+
std::cout << "Loading dependency: \"" << dep_file.generic_string() << "\"\n";
106106
if (!registry.load_package(dep_file))
107107
{
108108
throw std::runtime_error("Failed to load dependency: " + dep_file.string());
@@ -160,7 +160,7 @@ int main(int argc, char *argv[])
160160
dep_files = resolver.sort_by_dependencies(dep_files);
161161
for (const auto &dep_file : dep_files)
162162
{
163-
std::cout << "Loading dependency: " << dep_file << "\n";
163+
std::cout << "Loading dependency: \"" << dep_file.generic_string() << "\"\n";
164164
if (!registry.load_package(dep_file))
165165
{
166166
throw std::runtime_error("Failed to load dependency: " + dep_file.string());

0 commit comments

Comments
 (0)