Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modules support (finish #425) #505

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Clang.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export Index
include("trans_unit.jl")
export TranslationUnit, spelling, parse_header, parse_headers

include("module.jl")
export get_module, ast_file, name
export parent_module, full_name, is_system
export toplevel_headers

include("cursor.jl")
export kind, name, spelling, value
export file, file_line_column
Expand Down
10 changes: 5 additions & 5 deletions src/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ Base.show(io::IO, x::CLFile) = print(io, """CLFile ("$(name(x))")""")


"""
get_filename(x::CXFile) -> String
Return the complete file and path name of the given file
get_filename(file::CXFile) -> String
Return the complete file and path name of the given `file`.
"""
function get_filename(file::CXFile)
name(CLFile(file))
end


"""
name(x::CLFile) -> String
Return the complete file and path name of the given file
name(file::CLFile) -> String
Return the complete file and path name of the given `file`.
"""
function name(file::CLFile)
file |> clang_getFileName |> _cxstring_to_string
end

"""
unique_id(file::CLFile) -> CXFileUniqueID
Return the unique id of the given file.
Return the unique id of the given `file`.
"""
function unique_id(file::CLFile)
id = Ref{CXFileUniqueID}()
Expand Down
72 changes: 72 additions & 0 deletions src/module.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
struct CLModule
mod::CXModule
end

Base.convert(::Type{CLModule}, x::CXModule) = CLModule(x)
Base.cconvert(::Type{CXModule}, x::CLModule) = x
Base.unsafe_convert(::Type{CXModule}, x::CLModule) = x.mod

Base.show(io::IO, x::CLModule) = print(io, "CLModule ($(full_name(x)))")

"""
get_module(tu::TranslationUnit, file::CLFile) -> CLModule
Given a CLFile header file, return the module that contains it, if one exists.
"""
function get_module(tu::TranslationUnit, file::CLFile)::CLModule
return Clang.clang_getModuleForFile(tu, file)
end

"""
ast_file(mod::CLModule) -> CLFile
Given a module, return the module file where the provided module object came from.
"""
function ast_file(mod::CLModule)::CLFile
return Clang.clang_Module_getASTFile(mod)
end

"""
parent_module(mod::CLModule) -> CLModule
Given a module, return the parent of a sub-module or NULL if the given module is top-level,
e.g. for 'std.vector' it will return the 'std' module.
"""
function parent_module(mod::CLModule)::CLModule
return Clang.clang_Module_getParent(mod)
end

"""
name(mod::CLModule)
Given a module, return the name of the module,
e.g. for the 'std.vector' sub-module it will return "vector".
"""
function name(mod::CLModule)
return Clang.clang_Module_getName(mod) |> _cxstring_to_string
end

"""
full_name(mod::CLModule)
Given a module, return the full name of the module, e.g. "std.vector".
"""
function full_name(mod::CLModule)
return Clang.clang_Module_getFullName(mod) |> _cxstring_to_string
end

"""
is_system(mod::CLModule)
Given a module, return whether it is a system one.
"""
function is_system(mod::CLModule)
return Bool(Clang.clang_Module_isSystem(mod))
end

"""
toplevel_headers(tu::TranslationUnit, mod::CLModule)
Given a module, return all top level headers associated with the module.
"""
function toplevel_headers(tu::TranslationUnit, mod::CLModule)
num = Clang.clang_Module_getNumTopLevelHeaders(tu, mod)
headers = Vector{CLFile}(undef, num)
for i=1:num
headers[i] = Clang.clang_Module_getTopLevelHeader(tu, mod, i-1)
end
return headers
end
53 changes: 53 additions & 0 deletions test/module.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Clang
# using Test

@testset "Module" begin
modulemap = """
module foo {
module bar [system] {
header "test.h"
export *
}
}

"""
header = """
#pragma once
typedef struct {int a;int b;} Bar;
"""

source = """
@import foo.bar;
"""

dir = mktempdir()
args = [
"-x",
"objective-c",
"-fmodules",
"-I$dir",
]

create(f,s) = begin
fp = joinpath(dir,f);
open(fp,"w") do io
print(io,s)
end
fp
end

create("module.modulemap", modulemap)
h = create("test.h", header)
f = create("source.h", source)

index = Index()
tu = parse_header(index, f, args)
f = tu |> Clang.getTranslationUnitCursor |> children |> first |> file
mod = get_module(tu, f)
@test name(mod) == "bar"
@test full_name(mod) == "foo.bar"
@test full_name(parent_module(mod)) == "foo"
@test toplevel_headers(tu,mod) |> only |> name |> normpath == h
@test is_system(mod) == true
@test ast_file(mod) |> name != ""
end
2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ using REPL

include("jllenvs.jl")
include("file.jl")
include("module.jl")

include("generators.jl")

include("test_mpi.jl")
Expand Down