Skip to content

Commit 572eddf

Browse files
Modules support (finish #425) (#505)
* Module support * Minor fixes to docstrings * Add docstrings for module support * Fix Windows tests --------- Co-authored-by: Nehal Patel <nehal@alum.mit.edu>
1 parent ce61d3e commit 572eddf

File tree

5 files changed

+136
-5
lines changed

5 files changed

+136
-5
lines changed

src/Clang.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export Index
4646
include("trans_unit.jl")
4747
export TranslationUnit, spelling, parse_header, parse_headers
4848

49+
include("module.jl")
50+
export get_module, ast_file, name
51+
export parent_module, full_name, is_system
52+
export toplevel_headers
53+
4954
include("cursor.jl")
5055
export kind, name, spelling, value
5156
export file, file_line_column

src/file.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ Base.show(io::IO, x::CLFile) = print(io, """CLFile ("$(name(x))")""")
1010

1111

1212
"""
13-
get_filename(x::CXFile) -> String
14-
Return the complete file and path name of the given file
13+
get_filename(file::CXFile) -> String
14+
Return the complete file and path name of the given `file`.
1515
"""
1616
function get_filename(file::CXFile)
1717
name(CLFile(file))
1818
end
1919

2020

2121
"""
22-
name(x::CLFile) -> String
23-
Return the complete file and path name of the given file
22+
name(file::CLFile) -> String
23+
Return the complete file and path name of the given `file`.
2424
"""
2525
function name(file::CLFile)
2626
file |> clang_getFileName |> _cxstring_to_string
2727
end
2828

2929
"""
3030
unique_id(file::CLFile) -> CXFileUniqueID
31-
Return the unique id of the given file.
31+
Return the unique id of the given `file`.
3232
"""
3333
function unique_id(file::CLFile)
3434
id = Ref{CXFileUniqueID}()

src/module.jl

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
struct CLModule
2+
mod::CXModule
3+
end
4+
5+
Base.convert(::Type{CLModule}, x::CXModule) = CLModule(x)
6+
Base.cconvert(::Type{CXModule}, x::CLModule) = x
7+
Base.unsafe_convert(::Type{CXModule}, x::CLModule) = x.mod
8+
9+
Base.show(io::IO, x::CLModule) = print(io, "CLModule ($(full_name(x)))")
10+
11+
"""
12+
get_module(tu::TranslationUnit, file::CLFile) -> CLModule
13+
Given a CLFile header file, return the module that contains it, if one exists.
14+
"""
15+
function get_module(tu::TranslationUnit, file::CLFile)::CLModule
16+
return Clang.clang_getModuleForFile(tu, file)
17+
end
18+
19+
"""
20+
ast_file(mod::CLModule) -> CLFile
21+
Given a module, return the module file where the provided module object came from.
22+
"""
23+
function ast_file(mod::CLModule)::CLFile
24+
return Clang.clang_Module_getASTFile(mod)
25+
end
26+
27+
"""
28+
parent_module(mod::CLModule) -> CLModule
29+
Given a module, return the parent of a sub-module or NULL if the given module is top-level,
30+
e.g. for 'std.vector' it will return the 'std' module.
31+
"""
32+
function parent_module(mod::CLModule)::CLModule
33+
return Clang.clang_Module_getParent(mod)
34+
end
35+
36+
"""
37+
name(mod::CLModule)
38+
Given a module, return the name of the module,
39+
e.g. for the 'std.vector' sub-module it will return "vector".
40+
"""
41+
function name(mod::CLModule)
42+
return Clang.clang_Module_getName(mod) |> _cxstring_to_string
43+
end
44+
45+
"""
46+
full_name(mod::CLModule)
47+
Given a module, return the full name of the module, e.g. "std.vector".
48+
"""
49+
function full_name(mod::CLModule)
50+
return Clang.clang_Module_getFullName(mod) |> _cxstring_to_string
51+
end
52+
53+
"""
54+
is_system(mod::CLModule)
55+
Given a module, return whether it is a system one.
56+
"""
57+
function is_system(mod::CLModule)
58+
return Bool(Clang.clang_Module_isSystem(mod))
59+
end
60+
61+
"""
62+
toplevel_headers(tu::TranslationUnit, mod::CLModule)
63+
Given a module, return all top level headers associated with the module.
64+
"""
65+
function toplevel_headers(tu::TranslationUnit, mod::CLModule)
66+
num = Clang.clang_Module_getNumTopLevelHeaders(tu, mod)
67+
headers = Vector{CLFile}(undef, num)
68+
for i=1:num
69+
headers[i] = Clang.clang_Module_getTopLevelHeader(tu, mod, i-1)
70+
end
71+
return headers
72+
end

test/ClangTests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using ReTest
1616
include("jllenvs.jl")
1717
include("file.jl")
1818
include("generators.jl")
19+
include("module.jl")
1920

2021
include("test_mpi.jl")
2122
include("test_bitfield.jl")

test/module.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Clang
2+
# using Test
3+
4+
@testset "Module" begin
5+
modulemap = """
6+
module foo {
7+
module bar [system] {
8+
header "test.h"
9+
export *
10+
}
11+
}
12+
13+
"""
14+
header = """
15+
#pragma once
16+
typedef struct {int a;int b;} Bar;
17+
"""
18+
19+
source = """
20+
@import foo.bar;
21+
"""
22+
23+
dir = mktempdir()
24+
args = [
25+
"-x",
26+
"objective-c",
27+
"-fmodules",
28+
"-I$dir",
29+
]
30+
31+
create(f,s) = begin
32+
fp = joinpath(dir,f);
33+
open(fp,"w") do io
34+
print(io,s)
35+
end
36+
fp
37+
end
38+
39+
create("module.modulemap", modulemap)
40+
h = create("test.h", header)
41+
f = create("source.h", source)
42+
43+
index = Index()
44+
tu = parse_header(index, f, args)
45+
f = tu |> Clang.getTranslationUnitCursor |> children |> first |> file
46+
mod = get_module(tu, f)
47+
@test name(mod) == "bar"
48+
@test full_name(mod) == "foo.bar"
49+
@test full_name(parent_module(mod)) == "foo"
50+
@test toplevel_headers(tu,mod) |> only |> name |> normpath == h
51+
@test is_system(mod) == true
52+
@test ast_file(mod) |> name != ""
53+
end

0 commit comments

Comments
 (0)