<commit_before>module cindex

###############################################################################

export parse, cu_type, cu_kind, ty_kind, name, spelling, is_function, is_null,
       value, children, cu_file, resolve_type, return_type
export CXType, CXCursor, CXString, CXTypeKind, CursorList

import Base.getindex, Base.start, Base.next, Base.done, Base.search

###############################################################################

# Types and global definitions

# Name of the helper library
const libwci = :libwrapclang

# Type definitions for wrapped types
typealias CXIndex Ptr{Void}
typealias CXUnsavedFile Ptr{Void}
typealias CXFile Ptr{Void}
typealias CXTypeKind Int32
typealias CXCursorKind Int32
typealias CXTranslationUnit Ptr{Void}
const CXString_size = ccall( ("wci_size_CXString", libwci), Int, ())

# Work-around: ccall followed by composite_type in @eval gives error.
get_sz(sym) = @eval ccall( ($(string("wci_size_", sym)), :($(libwci))), Int, ())

# Generate container types
for st in Any[
        :CXSourceLocation, :CXSourceRange,
        :CXTUResourceUsageEntry, :CXTUResourceUsage, :CXCursor, :CXType,
        :CXToken ]
    sz_name = symbol(string(st,"_size"))
    @eval begin
        const $sz_name = get_sz($("$st"))
        immutable $(st)
            data::Array{Uint8,1}
            $st() = new(Array(Uint8, $sz_name))
        end
    end
end

immutable CXString
    data::Array{Uint8,1}
    str::ASCIIString
    CXString() = new(Array(Uint8, CXString_size), "")
end

type CursorList
    ptr::Ptr{Void}
    size::Int
end

function get_string(cx::CXString)
    p::Ptr{Uint8} = ccall( (:wci_getCString, libwci), 
        Ptr{Uint8}, (Ptr{Void},), cx.data)
    if (p == C_NULL)
        return ""
    end
    bytestring(p)
end

###############################################################################
# Include the wrapper functions which do the struct copying
# These include statements must follow type definitions above
# because the wrapped functions use those types.

include("cindex_base.jl")
include("cindex_h.jl")

###############################################################################

# Main entry point for parsing
# Returns root CXCursor in the TranslationUnit for a given header
#
# Required argument:
#   "header.h"          header file to parse
#
# Optional (keyword) arguments:
#   ClangIndex:         CXIndex pointer (pass to avoid re-allocation)
#   ClangDiagnostics:   Display Clang diagnostics
#   CPlusPlus:          Parse as C++
#   ClangArgs   :       Compiler switches as string array, eg: ["-x", "c++", "-fno-elide-type"]
#   ParserOptions:      Bitwise OR of CXTranslationUnit_* flags (see docs, rarely needed)
#
function parse(header::String;
                ClangIndex                      = None,
                ClangDiagnostics::Bool          = false,
                CPlusPlus::Bool                 = false,
                ClangArgs                       = [""],
                ParserOptions                   = 0)
    if (ClangIndex == None)
        ClangIndex = idx_create(0, (ClangDiagnostics ? 0 : 1))
    end
    if (CPlusPlus)
        push!(ClangOptions, ["-x", "c++"])
    end
    
    tu = tu_parse(ClangIndex, header, ClangArgs, length(ClangArgs),
                  C_NULL, 0, ParserOptions)
    if (tu == C_NULL)
        error("ParseTranslationUnit returned NULL; unable to create TranslationUnit")
    end
    
    return tu_cursor(tu)
end

###############################################################################

# TODO: macro version should be more efficient.
anymatch(first, args...) = any({==(first, a) for a in args})

cu_type(c::CXCursor) = getCursorType(c)
cu_kind(c::CXCursor) = getCursorKind(c)
ty_kind(c::CXType) = reinterpret(Int32, c.data[1:4])[1]<commit_msg>Add cindex.search: find cursor in CursorList<commit_after>module cindex

###############################################################################

export parse, cu_type, cu_kind, ty_kind, name, spelling, is_function, is_null,
       value, children, cu_file, resolve_type, return_type
export CXType, CXCursor, CXString, CXTypeKind, CursorList

import Base.getindex, Base.start, Base.next, Base.done, Base.search, Base.show

###############################################################################

# Types and global definitions

# Name of the helper library
const libwci = :libwrapclang

# Type definitions for wrapped types
typealias CXIndex Ptr{Void}
typealias CXUnsavedFile Ptr{Void}
typealias CXFile Ptr{Void}
typealias CXTypeKind Int32
typealias CXCursorKind Int32
typealias CXTranslationUnit Ptr{Void}
const CXString_size = ccall( ("wci_size_CXString", libwci), Int, ())

# Work-around: ccall followed by composite_type in @eval gives error.
get_sz(sym) = @eval ccall( ($(string("wci_size_", sym)), :($(libwci))), Int, ())

# Generate container types
for st in Any[
        :CXSourceLocation, :CXSourceRange,
        :CXTUResourceUsageEntry, :CXTUResourceUsage, :CXCursor, :CXType,
        :CXToken ]
    sz_name = symbol(string(st,"_size"))
    @eval begin
        const $sz_name = get_sz($("$st"))
        immutable $(st)
            data::Array{Uint8,1}
            $st() = new(Array(Uint8, $sz_name))
        end
    end
end

immutable CXString
    data::Array{Uint8,1}
    str::ASCIIString
    CXString() = new(Array(Uint8, CXString_size), "")
end

type CursorList
    ptr::Ptr{Void}
    size::Int
end

function get_string(cx::CXString)
    p::Ptr{Uint8} = ccall( (:wci_getCString, libwci), 
        Ptr{Uint8}, (Ptr{Void},), cx.data)
    if (p == C_NULL)
        return ""
    end
    bytestring(p)
end

###############################################################################
# Include the wrapper functions which do the struct copying
# These include statements must follow type definitions above
# because the wrapped functions use those types.

include("cindex_base.jl")
include("cindex_h.jl")

###############################################################################

# Main entry point for parsing
# Returns root CXCursor in the TranslationUnit for a given header
#
# Required argument:
#   "header.h"          header file to parse
#
# Optional (keyword) arguments:
#   ClangIndex:         CXIndex pointer (pass to avoid re-allocation)
#   ClangDiagnostics:   Display Clang diagnostics
#   CPlusPlus:          Parse as C++
#   ClangArgs   :       Compiler switches as string array, eg: ["-x", "c++", "-fno-elide-type"]
#   ParserOptions:      Bitwise OR of CXTranslationUnit_* flags (see docs, rarely needed)
#
function parse(header::String;
                ClangIndex                      = None,
                ClangDiagnostics::Bool          = false,
                CPlusPlus::Bool                 = false,
                ClangArgs                       = [""],
                ParserOptions                   = 0)
    if (ClangIndex == None)
        ClangIndex = idx_create(0, (ClangDiagnostics ? 0 : 1))
    end
    if (CPlusPlus)
        push!(ClangOptions, ["-x", "c++"])
    end
    
    tu = tu_parse(ClangIndex, header, ClangArgs, length(ClangArgs),
                  C_NULL, 0, ParserOptions)
    if (tu == C_NULL)
        error("ParseTranslationUnit returned NULL; unable to create TranslationUnit")
    end
    
    return tu_cursor(tu)
end


# Search function for CursorList
# Returns vector of CXCursors in CursorList matching predicate
#
# Required arguments:
#   CursorList      List to search
#   IsMatch(CXCursor)
#                   Predicate Function, accepting a CXCursor argument
#
function search(cl::CursorList, ismatch::Function)
    ret = CXCursor[]
    for cu in cl
        ismatch(cu) && push!(ret, cu)
    end
    ret
end
search(cu::CXCursor, ismatch::Function) = search(children(cu), ismatch)

show(io::IO, cu::CXCursor) = print(io, "CXCursor: ", name(cu), " kind: ", cu_kind(cu))

###############################################################################

# TODO: macro version should be more efficient.
anymatch(first, args...) = any({==(first, a) for a in args})

cu_type(c::CXCursor) = getCursorType(c)
cu_kind(c::CXCursor) = getCursorKind(c)
ty_kind(c::CXType) = reinterpret(Int32, c.data[1:4])[1]
{'fraction_non_alphanumeric': 0.19845928099779897, 'fraction_numerical': 0.005380288579114698, 'mean_word_length': 3.4914881933003845, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3251675', 'n_tokens_mistral': 2526, 'n_tokens_neox': 2396, 'n_words': 656}