| ... | ... | @@ -739,6 +739,7 @@ pub const Scope = struct { |
| 739 | 739 | } |
| 740 | 740 | |
| 741 | 741 | pub fn deinit(file: *File, gpa: *Allocator) void { |
| 742 | gpa.free(file.sub_file_path); |
| 742 | 743 | file.unload(gpa); |
| 743 | 744 | file.* = undefined; |
| 744 | 745 | } |
| ... | ... | @@ -746,6 +747,11 @@ pub const Scope = struct { |
| 746 | 747 | pub fn getSource(file: *File, gpa: *Allocator) ![:0]const u8 { |
| 747 | 748 | if (file.source_loaded) return file.source; |
| 748 | 749 | |
| 750 | const root_dir_path = file.pkg.root_src_directory.path orelse "."; |
| 751 | log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{ |
| 752 | root_dir_path, file.sub_file_path, |
| 753 | }); |
| 754 | |
| 749 | 755 | // Keep track of inode, file size, mtime, hash so we can detect which files |
| 750 | 756 | // have been modified when an incremental update is requested. |
| 751 | 757 | var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); |
| ... | ... | @@ -2633,20 +2639,70 @@ pub const ImportFileResult = struct { |
| 2633 | 2639 | is_new: bool, |
| 2634 | 2640 | }; |
| 2635 | 2641 | |
| 2642 | pub fn importPkg(mod: *Module, cur_pkg: *Package, pkg: *Package) !ImportFileResult { |
| 2643 | const gpa = mod.gpa; |
| 2644 | |
| 2645 | // The resolved path is used as the key in the import table, to detect if |
| 2646 | // an import refers to the same as another, despite different relative paths |
| 2647 | // or differently mapped package names. |
| 2648 | const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{ |
| 2649 | pkg.root_src_directory.path orelse ".", pkg.root_src_path, |
| 2650 | }); |
| 2651 | var keep_resolved_path = false; |
| 2652 | defer if (!keep_resolved_path) gpa.free(resolved_path); |
| 2653 | |
| 2654 | const gop = try mod.import_table.getOrPut(gpa, resolved_path); |
| 2655 | if (gop.found_existing) return ImportFileResult{ |
| 2656 | .file = gop.entry.value, |
| 2657 | .is_new = false, |
| 2658 | }; |
| 2659 | keep_resolved_path = true; // It's now owned by import_table. |
| 2660 | |
| 2661 | const sub_file_path = try gpa.dupe(u8, pkg.root_src_path); |
| 2662 | errdefer gpa.free(sub_file_path); |
| 2663 | |
| 2664 | const new_file = try gpa.create(Scope.File); |
| 2665 | errdefer gpa.destroy(new_file); |
| 2666 | |
| 2667 | gop.entry.value = new_file; |
| 2668 | new_file.* = .{ |
| 2669 | .sub_file_path = sub_file_path, |
| 2670 | .source = undefined, |
| 2671 | .source_loaded = false, |
| 2672 | .tree_loaded = false, |
| 2673 | .zir_loaded = false, |
| 2674 | .stat_size = undefined, |
| 2675 | .stat_inode = undefined, |
| 2676 | .stat_mtime = undefined, |
| 2677 | .tree = undefined, |
| 2678 | .zir = undefined, |
| 2679 | .status = .never_loaded, |
| 2680 | .pkg = pkg, |
| 2681 | .namespace = undefined, |
| 2682 | }; |
| 2683 | return ImportFileResult{ |
| 2684 | .file = new_file, |
| 2685 | .is_new = true, |
| 2686 | }; |
| 2687 | } |
| 2688 | |
| 2636 | 2689 | pub fn importFile( |
| 2637 | 2690 | mod: *Module, |
| 2638 | | cur_pkg: *Package, |
| 2691 | cur_file: *Scope.File, |
| 2639 | 2692 | import_string: []const u8, |
| 2640 | 2693 | ) !ImportFileResult { |
| 2694 | if (cur_file.pkg.table.get(import_string)) |pkg| { |
| 2695 | return mod.importPkg(cur_file.pkg, pkg); |
| 2696 | } |
| 2641 | 2697 | const gpa = mod.gpa; |
| 2642 | 2698 | |
| 2643 | | const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse "."; |
| 2644 | | const found_pkg = cur_pkg.table.get(import_string); |
| 2645 | | |
| 2646 | | const resolved_path = if (found_pkg) |pkg| |
| 2647 | | try std.fs.path.resolve(gpa, &[_][]const u8{ pkg.root_src_directory.path orelse ".", pkg.root_src_path }) |
| 2648 | | else |
| 2649 | | try std.fs.path.resolve(gpa, &[_][]const u8{ cur_pkg_dir_path, import_string }); |
| 2699 | // The resolved path is used as the key in the import table, to detect if |
| 2700 | // an import refers to the same as another, despite different relative paths |
| 2701 | // or differently mapped package names. |
| 2702 | const cur_pkg_dir_path = cur_file.pkg.root_src_directory.path orelse "."; |
| 2703 | const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{ |
| 2704 | cur_pkg_dir_path, cur_file.sub_file_path, "..", import_string, |
| 2705 | }); |
| 2650 | 2706 | var keep_resolved_path = false; |
| 2651 | 2707 | defer if (!keep_resolved_path) gpa.free(resolved_path); |
| 2652 | 2708 | |
| ... | ... | @@ -2655,20 +2711,28 @@ pub fn importFile( |
| 2655 | 2711 | .file = gop.entry.value, |
| 2656 | 2712 | .is_new = false, |
| 2657 | 2713 | }; |
| 2714 | keep_resolved_path = true; // It's now owned by import_table. |
| 2658 | 2715 | |
| 2659 | | if (found_pkg == null) { |
| 2660 | | const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path}); |
| 2661 | | defer gpa.free(resolved_root_path); |
| 2716 | const new_file = try gpa.create(Scope.File); |
| 2717 | errdefer gpa.destroy(new_file); |
| 2662 | 2718 | |
| 2663 | | if (!mem.startsWith(u8, resolved_path, resolved_root_path)) { |
| 2664 | | return error.ImportOutsidePkgPath; |
| 2665 | | } |
| 2719 | const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path}); |
| 2720 | defer gpa.free(resolved_root_path); |
| 2721 | |
| 2722 | if (!mem.startsWith(u8, resolved_path, resolved_root_path)) { |
| 2723 | return error.ImportOutsidePkgPath; |
| 2666 | 2724 | } |
| 2725 | // +1 for the directory separator here. |
| 2726 | const sub_file_path = try gpa.dupe(u8, resolved_path[resolved_root_path.len + 1 ..]); |
| 2727 | errdefer gpa.free(sub_file_path); |
| 2728 | |
| 2729 | log.debug("new importFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, import_string={s}", .{ |
| 2730 | resolved_root_path, resolved_path, sub_file_path, import_string, |
| 2731 | }); |
| 2667 | 2732 | |
| 2668 | | const new_file = try gpa.create(Scope.File); |
| 2669 | 2733 | gop.entry.value = new_file; |
| 2670 | 2734 | new_file.* = .{ |
| 2671 | | .sub_file_path = resolved_path, |
| 2735 | .sub_file_path = sub_file_path, |
| 2672 | 2736 | .source = undefined, |
| 2673 | 2737 | .source_loaded = false, |
| 2674 | 2738 | .tree_loaded = false, |
| ... | ... | @@ -2679,10 +2743,9 @@ pub fn importFile( |
| 2679 | 2743 | .tree = undefined, |
| 2680 | 2744 | .zir = undefined, |
| 2681 | 2745 | .status = .never_loaded, |
| 2682 | | .pkg = found_pkg orelse cur_pkg, |
| 2746 | .pkg = cur_file.pkg, |
| 2683 | 2747 | .namespace = undefined, |
| 2684 | 2748 | }; |
| 2685 | | keep_resolved_path = true; |
| 2686 | 2749 | return ImportFileResult{ |
| 2687 | 2750 | .file = new_file, |
| 2688 | 2751 | .is_new = true, |