ffi_gen 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -4
- data/lib/ffi_gen.rb +254 -378
- data/lib/ffi_gen/clang.rb +40 -38
- data/lib/ffi_gen/java_output.rb +242 -0
- data/lib/ffi_gen/ruby_output.rb +251 -0
- metadata +12 -5
data/lib/ffi_gen/clang.rb
CHANGED
@@ -8,6 +8,7 @@ module FFIGen::Clang
|
|
8
8
|
|
9
9
|
# A single translation unit, which resides in an index.
|
10
10
|
class TranslationUnitImpl < FFI::Struct
|
11
|
+
layout :dummy, :char
|
11
12
|
end
|
12
13
|
|
13
14
|
# Provides the contents of a file that has not yet been saved to disk.
|
@@ -316,7 +317,7 @@ module FFIGen::Clang
|
|
316
317
|
# @method get_presumed_location(location, filename, line, column)
|
317
318
|
# @param [SourceLocation] location the location within a source file that will be decomposed
|
318
319
|
# into its parts.
|
319
|
-
# @param [
|
320
|
+
# @param [String] filename (out) if non-NULL, will be set to the filename of the
|
320
321
|
# source location. Note that filenames returned will be for "virtual" files,
|
321
322
|
# which don't necessarily exist on the machine running clang - e.g. when
|
322
323
|
# parsing preprocessed output obtained from a different environment. If
|
@@ -329,7 +330,7 @@ module FFIGen::Clang
|
|
329
330
|
# source location. For an invalid source location, zero is returned.
|
330
331
|
# @return [nil]
|
331
332
|
# @scope class
|
332
|
-
attach_function :get_presumed_location, :clang_getPresumedLocation, [SourceLocation.by_value,
|
333
|
+
attach_function :get_presumed_location, :clang_getPresumedLocation, [SourceLocation.by_value, String, :pointer, :pointer], :void
|
333
334
|
|
334
335
|
# Legacy API to retrieve the file, line, column, and offset represented
|
335
336
|
# by the given source location.
|
@@ -565,12 +566,12 @@ module FFIGen::Clang
|
|
565
566
|
#
|
566
567
|
# @method get_diagnostic_option(diag, disable)
|
567
568
|
# @param [FFI::Pointer(Diagnostic)] diag The diagnostic to be queried.
|
568
|
-
# @param [
|
569
|
+
# @param [String] disable If non-NULL, will be set to the option that disables this
|
569
570
|
# diagnostic (if any).
|
570
571
|
# @return [String] A string that contains the command-line option used to enable this
|
571
572
|
# warning, such as "-Wconversion" or "-pedantic".
|
572
573
|
# @scope class
|
573
|
-
attach_function :get_diagnostic_option, :clang_getDiagnosticOption, [:pointer,
|
574
|
+
attach_function :get_diagnostic_option, :clang_getDiagnosticOption, [:pointer, String], String.by_value
|
574
575
|
|
575
576
|
# Retrieve the category number for this diagnostic.
|
576
577
|
#
|
@@ -640,14 +641,14 @@ module FFIGen::Clang
|
|
640
641
|
# @method get_diagnostic_fix_it(diagnostic, fix_it, replacement_range)
|
641
642
|
# @param [FFI::Pointer(Diagnostic)] diagnostic The diagnostic whose fix-its are being queried.
|
642
643
|
# @param [Integer] fix_it The zero-based index of the fix-it.
|
643
|
-
# @param [
|
644
|
+
# @param [SourceRange] replacement_range The source range whose contents will be
|
644
645
|
# replaced with the returned replacement string. Note that source
|
645
646
|
# ranges are half-open ranges (a, b), so the source code should be
|
646
647
|
# replaced from a and up to (but not including) b.
|
647
648
|
# @return [String] A string containing text that should be replace the source
|
648
649
|
# code indicated by the \c ReplacementRange.
|
649
650
|
# @scope class
|
650
|
-
attach_function :get_diagnostic_fix_it, :clang_getDiagnosticFixIt, [:pointer, :uint,
|
651
|
+
attach_function :get_diagnostic_fix_it, :clang_getDiagnosticFixIt, [:pointer, :uint, SourceRange], String.by_value
|
651
652
|
|
652
653
|
# Get the original translation unit source file name.
|
653
654
|
#
|
@@ -1961,6 +1962,7 @@ module FFIGen::Clang
|
|
1961
1962
|
|
1962
1963
|
# A fast container representing a set of CXCursors.
|
1963
1964
|
class CursorSetImpl < FFI::Struct
|
1965
|
+
layout :dummy, :char
|
1964
1966
|
end
|
1965
1967
|
|
1966
1968
|
# Creates an empty CXCursorSet.
|
@@ -2120,10 +2122,10 @@ module FFIGen::Clang
|
|
2120
2122
|
# clang_getOverriddenCursors().
|
2121
2123
|
#
|
2122
2124
|
# @method dispose_overridden_cursors(overridden)
|
2123
|
-
# @param [
|
2125
|
+
# @param [Cursor] overridden
|
2124
2126
|
# @return [nil]
|
2125
2127
|
# @scope class
|
2126
|
-
attach_function :dispose_overridden_cursors, :clang_disposeOverriddenCursors, [
|
2128
|
+
attach_function :dispose_overridden_cursors, :clang_disposeOverriddenCursors, [Cursor], :void
|
2127
2129
|
|
2128
2130
|
# Retrieve the file that is included by the given inclusion directive
|
2129
2131
|
# cursor.
|
@@ -3025,23 +3027,23 @@ module FFIGen::Clang
|
|
3025
3027
|
#
|
3026
3028
|
# @method annotate_tokens(tu, tokens, num_tokens, cursors)
|
3027
3029
|
# @param [TranslationUnitImpl] tu the translation unit that owns the given tokens.
|
3028
|
-
# @param [
|
3030
|
+
# @param [Token] tokens the set of tokens to annotate.
|
3029
3031
|
# @param [Integer] num_tokens the number of tokens in \p Tokens.
|
3030
|
-
# @param [
|
3032
|
+
# @param [Cursor] cursors an array of \p NumTokens cursors, whose contents will be
|
3031
3033
|
# replaced with the cursors corresponding to each token.
|
3032
3034
|
# @return [nil]
|
3033
3035
|
# @scope class
|
3034
|
-
attach_function :annotate_tokens, :clang_annotateTokens, [TranslationUnitImpl,
|
3036
|
+
attach_function :annotate_tokens, :clang_annotateTokens, [TranslationUnitImpl, Token, :uint, Cursor], :void
|
3035
3037
|
|
3036
3038
|
# Free the given set of tokens.
|
3037
3039
|
#
|
3038
3040
|
# @method dispose_tokens(tu, tokens, num_tokens)
|
3039
3041
|
# @param [TranslationUnitImpl] tu
|
3040
|
-
# @param [
|
3042
|
+
# @param [Token] tokens
|
3041
3043
|
# @param [Integer] num_tokens
|
3042
3044
|
# @return [nil]
|
3043
3045
|
# @scope class
|
3044
|
-
attach_function :dispose_tokens, :clang_disposeTokens, [TranslationUnitImpl,
|
3046
|
+
attach_function :dispose_tokens, :clang_disposeTokens, [TranslationUnitImpl, Token, :uint], :void
|
3045
3047
|
|
3046
3048
|
# for debug/testing
|
3047
3049
|
#
|
@@ -3357,12 +3359,12 @@ module FFIGen::Clang
|
|
3357
3359
|
#
|
3358
3360
|
# = Fields:
|
3359
3361
|
# :results ::
|
3360
|
-
# (
|
3362
|
+
# (CompletionResult) The code-completion results.
|
3361
3363
|
# :num_results ::
|
3362
3364
|
# (Integer) The number of code-completion results stored in the
|
3363
3365
|
# \c Results array.
|
3364
3366
|
class CodeCompleteResults < FFI::Struct
|
3365
|
-
layout :results,
|
3367
|
+
layout :results, CompletionResult,
|
3366
3368
|
:num_results, :uint
|
3367
3369
|
end
|
3368
3370
|
|
@@ -3473,39 +3475,39 @@ module FFIGen::Clang
|
|
3473
3475
|
# CXCodeComplete_Flags enumeration. The
|
3474
3476
|
# \c clang_defaultCodeCompleteOptions() function returns a default set
|
3475
3477
|
# of code-completion options.
|
3476
|
-
# @return [
|
3478
|
+
# @return [CodeCompleteResults] If successful, a new \c CXCodeCompleteResults structure
|
3477
3479
|
# containing code-completion results, which should eventually be
|
3478
3480
|
# freed with \c clang_disposeCodeCompleteResults(). If code
|
3479
3481
|
# completion fails, returns NULL.
|
3480
3482
|
# @scope class
|
3481
|
-
attach_function :code_complete_at, :clang_codeCompleteAt, [TranslationUnitImpl, :string, :uint, :uint, UnsavedFile, :uint, :uint],
|
3483
|
+
attach_function :code_complete_at, :clang_codeCompleteAt, [TranslationUnitImpl, :string, :uint, :uint, UnsavedFile, :uint, :uint], CodeCompleteResults
|
3482
3484
|
|
3483
3485
|
# Sort the code-completion results in case-insensitive alphabetical
|
3484
3486
|
# order.
|
3485
3487
|
#
|
3486
3488
|
# @method sort_code_completion_results(results, num_results)
|
3487
|
-
# @param [
|
3489
|
+
# @param [CompletionResult] results The set of results to sort.
|
3488
3490
|
# @param [Integer] num_results The number of results in \p Results.
|
3489
3491
|
# @return [nil]
|
3490
3492
|
# @scope class
|
3491
|
-
attach_function :sort_code_completion_results, :clang_sortCodeCompletionResults, [
|
3493
|
+
attach_function :sort_code_completion_results, :clang_sortCodeCompletionResults, [CompletionResult, :uint], :void
|
3492
3494
|
|
3493
3495
|
# Free the given set of code-completion results.
|
3494
3496
|
#
|
3495
3497
|
# @method dispose_code_complete_results(results)
|
3496
|
-
# @param [
|
3498
|
+
# @param [CodeCompleteResults] results
|
3497
3499
|
# @return [nil]
|
3498
3500
|
# @scope class
|
3499
|
-
attach_function :dispose_code_complete_results, :clang_disposeCodeCompleteResults, [
|
3501
|
+
attach_function :dispose_code_complete_results, :clang_disposeCodeCompleteResults, [CodeCompleteResults], :void
|
3500
3502
|
|
3501
3503
|
# Determine the number of diagnostics produced prior to the
|
3502
3504
|
# location where code completion was performed.
|
3503
3505
|
#
|
3504
3506
|
# @method code_complete_get_num_diagnostics(results)
|
3505
|
-
# @param [
|
3507
|
+
# @param [CodeCompleteResults] results
|
3506
3508
|
# @return [Integer]
|
3507
3509
|
# @scope class
|
3508
|
-
attach_function :code_complete_get_num_diagnostics, :clang_codeCompleteGetNumDiagnostics, [
|
3510
|
+
attach_function :code_complete_get_num_diagnostics, :clang_codeCompleteGetNumDiagnostics, [CodeCompleteResults], :uint
|
3509
3511
|
|
3510
3512
|
# Retrieve a diagnostic associated with the given code completion.
|
3511
3513
|
#
|
@@ -3513,22 +3515,22 @@ module FFIGen::Clang
|
|
3513
3515
|
# the code completion results to query.
|
3514
3516
|
#
|
3515
3517
|
# @method code_complete_get_diagnostic(results, index)
|
3516
|
-
# @param [
|
3518
|
+
# @param [CodeCompleteResults] results
|
3517
3519
|
# @param [Integer] index the zero-based diagnostic number to retrieve.
|
3518
3520
|
# @return [FFI::Pointer(Diagnostic)] the requested diagnostic. This diagnostic must be freed
|
3519
3521
|
# via a call to \c clang_disposeDiagnostic().
|
3520
3522
|
# @scope class
|
3521
|
-
attach_function :code_complete_get_diagnostic, :clang_codeCompleteGetDiagnostic, [
|
3523
|
+
attach_function :code_complete_get_diagnostic, :clang_codeCompleteGetDiagnostic, [CodeCompleteResults, :uint], :pointer
|
3522
3524
|
|
3523
3525
|
# Determines what compeltions are appropriate for the context
|
3524
3526
|
# the given code completion.
|
3525
3527
|
#
|
3526
3528
|
# @method code_complete_get_contexts(results)
|
3527
|
-
# @param [
|
3529
|
+
# @param [CodeCompleteResults] results the code completion results to query
|
3528
3530
|
# @return [Integer] the kinds of completions that are appropriate for use
|
3529
3531
|
# along with the given code completion results.
|
3530
3532
|
# @scope class
|
3531
|
-
attach_function :code_complete_get_contexts, :clang_codeCompleteGetContexts, [
|
3533
|
+
attach_function :code_complete_get_contexts, :clang_codeCompleteGetContexts, [CodeCompleteResults], :ulong_long
|
3532
3534
|
|
3533
3535
|
# Returns the cursor kind for the container for the current code
|
3534
3536
|
# completion context. The container is only guaranteed to be set for
|
@@ -3537,24 +3539,24 @@ module FFIGen::Clang
|
|
3537
3539
|
# CXCursor_InvalidCode.
|
3538
3540
|
#
|
3539
3541
|
# @method code_complete_get_container_kind(results, is_incomplete)
|
3540
|
-
# @param [
|
3542
|
+
# @param [CodeCompleteResults] results the code completion results to query
|
3541
3543
|
# @param [FFI::Pointer(*UInt)] is_incomplete on return, this value will be false if Clang has complete
|
3542
3544
|
# information about the container. If Clang does not have complete
|
3543
3545
|
# information, this value will be true.
|
3544
3546
|
# @return [Symbol from _enum_cursor_kind_] the container kind, or CXCursor_InvalidCode if there is not a
|
3545
3547
|
# container
|
3546
3548
|
# @scope class
|
3547
|
-
attach_function :code_complete_get_container_kind, :clang_codeCompleteGetContainerKind, [
|
3549
|
+
attach_function :code_complete_get_container_kind, :clang_codeCompleteGetContainerKind, [CodeCompleteResults, :pointer], :cursor_kind
|
3548
3550
|
|
3549
3551
|
# Returns the USR for the container for the current code completion
|
3550
3552
|
# context. If there is not a container for the current context, this
|
3551
3553
|
# function will return the empty string.
|
3552
3554
|
#
|
3553
3555
|
# @method code_complete_get_container_usr(results)
|
3554
|
-
# @param [
|
3556
|
+
# @param [CodeCompleteResults] results the code completion results to query
|
3555
3557
|
# @return [String] the USR for the container
|
3556
3558
|
# @scope class
|
3557
|
-
attach_function :code_complete_get_container_usr, :clang_codeCompleteGetContainerUSR, [
|
3559
|
+
attach_function :code_complete_get_container_usr, :clang_codeCompleteGetContainerUSR, [CodeCompleteResults], String.by_value
|
3558
3560
|
|
3559
3561
|
# Returns the currently-entered selector for an Objective-C message
|
3560
3562
|
# send, formatted like "initWithFoo:bar:". Only guaranteed to return a
|
@@ -3562,11 +3564,11 @@ module FFIGen::Clang
|
|
3562
3564
|
# CXCompletionContext_ObjCClassMessage.
|
3563
3565
|
#
|
3564
3566
|
# @method code_complete_get_obj_c_selector(results)
|
3565
|
-
# @param [
|
3567
|
+
# @param [CodeCompleteResults] results the code completion results to query
|
3566
3568
|
# @return [String] the selector (or partial selector) that has been entered thus far
|
3567
3569
|
# for an Objective-C message send.
|
3568
3570
|
# @scope class
|
3569
|
-
attach_function :code_complete_get_obj_c_selector, :clang_codeCompleteGetObjCSelector, [
|
3571
|
+
attach_function :code_complete_get_obj_c_selector, :clang_codeCompleteGetObjCSelector, [CodeCompleteResults], String.by_value
|
3570
3572
|
|
3571
3573
|
# Return a version string, suitable for showing to a user, but not
|
3572
3574
|
# intended to be parsed (the format is not guaranteed to be stable).
|
@@ -3601,12 +3603,12 @@ module FFIGen::Clang
|
|
3601
3603
|
# <em>This entry is only for documentation and no real method.</em>
|
3602
3604
|
#
|
3603
3605
|
# @method _callback_inclusion_visitor_(inclusion_stack, include_len, client_data)
|
3604
|
-
# @param [
|
3606
|
+
# @param [SourceLocation] inclusion_stack
|
3605
3607
|
# @param [Integer] include_len
|
3606
3608
|
# @param [FFI::Pointer(ClientData)] client_data
|
3607
3609
|
# @return [FFI::Pointer(File)]
|
3608
3610
|
# @scope class
|
3609
|
-
callback :inclusion_visitor, [
|
3611
|
+
callback :inclusion_visitor, [SourceLocation, :uint, :pointer], :pointer
|
3610
3612
|
|
3611
3613
|
# Visit the set of preprocessor inclusions in a translation unit.
|
3612
3614
|
# The visitor function is called with the provided data for every included
|
@@ -3643,12 +3645,12 @@ module FFIGen::Clang
|
|
3643
3645
|
# @method remap_get_filenames(remapping, index, original, transformed)
|
3644
3646
|
# @param [FFI::Pointer(Remapping)] remapping
|
3645
3647
|
# @param [Integer] index
|
3646
|
-
# @param [
|
3647
|
-
# @param [
|
3648
|
+
# @param [String] original If non-NULL, will be set to the original filename.
|
3649
|
+
# @param [String] transformed If non-NULL, will be set to the filename that the original
|
3648
3650
|
# is associated with.
|
3649
3651
|
# @return [nil]
|
3650
3652
|
# @scope class
|
3651
|
-
attach_function :remap_get_filenames, :clang_remap_getFilenames, [:pointer, :uint,
|
3653
|
+
attach_function :remap_get_filenames, :clang_remap_getFilenames, [:pointer, :uint, String, String], :void
|
3652
3654
|
|
3653
3655
|
# Dispose the remapping.
|
3654
3656
|
#
|
@@ -0,0 +1,242 @@
|
|
1
|
+
class FFIGen
|
2
|
+
def generate_java
|
3
|
+
writer = Writer.new " ", " * ", "/**", " */"
|
4
|
+
writer.puts "// Generated by ffi_gen. Please do not change this file by hand.", "import java.util.*;", "import com.sun.jna.*;", "import java.lang.annotation.*;", "import java.lang.reflect.Method;", "", "public interface #{@module_name} extends Library {"
|
5
|
+
writer.indent do
|
6
|
+
writer.puts "", *IO.readlines(File.join(File.dirname(__FILE__), "java_pre.java")).map(&:rstrip)
|
7
|
+
writer.puts "", "public static #{@module_name} INSTANCE = JnaInstanceCreator.createInstance();", ""
|
8
|
+
writer.puts "static class JnaInstanceCreator {"
|
9
|
+
writer.indent do
|
10
|
+
writer.puts "private static #{@module_name} createInstance() {"
|
11
|
+
writer.indent do
|
12
|
+
writer.puts "DefaultTypeMapper typeMapper = new DefaultTypeMapper();", "typeMapper.addFromNativeConverter(NativeEnum.class, new EnumConverter());", "typeMapper.addToNativeConverter(NativeEnum.class, new EnumConverter());", ""
|
13
|
+
writer.puts "Map<String, Object> options = new HashMap<String, Object>();", "options.put(Library.OPTION_FUNCTION_MAPPER, new NativeNameAnnotationFunctionMapper());", "options.put(Library.OPTION_TYPE_MAPPER, typeMapper);", ""
|
14
|
+
writer.puts "return (#{@module_name}) Native.loadLibrary(\"#{@ffi_lib}\", #{@module_name}.class, options);"
|
15
|
+
end
|
16
|
+
writer.puts "}"
|
17
|
+
end
|
18
|
+
writer.puts "}", ""
|
19
|
+
declarations.values.compact.uniq.each do |declaration|
|
20
|
+
declaration.write_java writer
|
21
|
+
end
|
22
|
+
end
|
23
|
+
writer.puts "}"
|
24
|
+
writer.output
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_java_type(full_type, is_array = false)
|
28
|
+
canonical_type = Clang.get_canonical_type full_type
|
29
|
+
data_array = case canonical_type[:kind]
|
30
|
+
when :void then ["void", "nil"]
|
31
|
+
when :bool then ["boolean", "Boolean"]
|
32
|
+
when :u_char then ["byte", "Integer"]
|
33
|
+
when :u_short then ["short", "Integer"]
|
34
|
+
when :u_int then ["int", "Integer"]
|
35
|
+
when :u_long then ["NativeLong", "Integer"]
|
36
|
+
when :u_long_long then ["long", "Integer"]
|
37
|
+
when :char_s, :s_char then ["byte", "Integer"]
|
38
|
+
when :short then ["short", "Integer"]
|
39
|
+
when :int then ["int", "Integer"]
|
40
|
+
when :long then ["NativeLong", "Integer"]
|
41
|
+
when :long_long then ["long", "Integer"]
|
42
|
+
when :float then ["float", "Float"]
|
43
|
+
when :double then ["double", "Float"]
|
44
|
+
when :pointer
|
45
|
+
if is_array
|
46
|
+
element_type = to_java_type Clang.get_pointee_type(canonical_type)
|
47
|
+
return { jna_type: "#{element_type[:jna_type]}[]", description: "Array of #{element_type[:description]}", parameter_name: element_type[:parameter_name] }
|
48
|
+
end
|
49
|
+
|
50
|
+
pointee_type = Clang.get_pointee_type canonical_type
|
51
|
+
result = nil
|
52
|
+
case pointee_type[:kind]
|
53
|
+
when :char_s
|
54
|
+
result = ["String", "String"]
|
55
|
+
when :record
|
56
|
+
pointee_declaration = @declarations[Clang.get_cursor_type(Clang.get_type_declaration(pointee_type))]
|
57
|
+
result = [pointee_declaration.java_name, pointee_declaration.java_name] if pointee_declaration and pointee_declaration.written
|
58
|
+
when :function_proto
|
59
|
+
declaration = @declarations[full_type]
|
60
|
+
result = [":#{declaration.java_name}", "Proc(_callback_#{declaration.java_name}_)"] if declaration
|
61
|
+
end
|
62
|
+
|
63
|
+
if result.nil?
|
64
|
+
pointer_depth = 0
|
65
|
+
pointer_target_name = ""
|
66
|
+
current_type = full_type
|
67
|
+
loop do
|
68
|
+
declaration = Clang.get_type_declaration current_type
|
69
|
+
pointer_target_name = Name.new self, Clang.get_cursor_spelling(declaration).to_s_and_dispose
|
70
|
+
break if not pointer_target_name.empty?
|
71
|
+
|
72
|
+
case current_type[:kind]
|
73
|
+
when :pointer
|
74
|
+
pointer_depth += 1
|
75
|
+
current_type = Clang.get_pointee_type current_type
|
76
|
+
when :unexposed
|
77
|
+
break
|
78
|
+
else
|
79
|
+
pointer_target_name = Name.new self, Clang.get_type_kind_spelling(current_type[:kind]).to_s_and_dispose
|
80
|
+
break
|
81
|
+
end
|
82
|
+
end
|
83
|
+
result = ["Pointer", "FFI::Pointer(#{'*' * pointer_depth}#{pointer_target_name.to_java_classname})", pointer_target_name]
|
84
|
+
end
|
85
|
+
|
86
|
+
result
|
87
|
+
when :record
|
88
|
+
declaration = @declarations[canonical_type]
|
89
|
+
declaration ? ["#{declaration.java_name}.by_value", declaration.java_name] : ["byte", "unknown"] # TODO
|
90
|
+
when :enum
|
91
|
+
declaration = @declarations[canonical_type]
|
92
|
+
declaration ? [declaration.java_name, "Symbol from _enum_#{declaration.java_name}_", declaration.name] : ["byte", "unknown"] # TODO
|
93
|
+
when :constant_array
|
94
|
+
element_type_data = to_java_type Clang.get_array_element_type(canonical_type)
|
95
|
+
size = Clang.get_array_size canonical_type
|
96
|
+
["[#{element_type_data[:jna_type]}, #{size}]", "Array<#{element_type_data[:description]}>"]
|
97
|
+
else
|
98
|
+
raise NotImplementedError, "No translation for values of type #{canonical_type[:kind]}"
|
99
|
+
end
|
100
|
+
|
101
|
+
{ jna_type: data_array[0], description: data_array[1], parameter_name: (data_array[2] || Name.new(self, data_array[1])).to_java_downcase }
|
102
|
+
end
|
103
|
+
|
104
|
+
class Name
|
105
|
+
JAVA_KEYWORDS = %w{abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while}
|
106
|
+
|
107
|
+
def to_java_downcase
|
108
|
+
format :camelcase, :initial_downcase, JAVA_KEYWORDS
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_java_classname
|
112
|
+
format :camelcase, JAVA_KEYWORDS
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_java_constant
|
116
|
+
format :upcase, :underscores, JAVA_KEYWORDS
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class Enum
|
121
|
+
def write_java(writer)
|
122
|
+
shorten_names
|
123
|
+
|
124
|
+
@constants.each do |constant|
|
125
|
+
constant[:symbol] = ":#{constant[:name].to_ruby_downcase}"
|
126
|
+
end
|
127
|
+
|
128
|
+
writer.comment do
|
129
|
+
writer.write_description @comment
|
130
|
+
# TODO constant comments
|
131
|
+
end
|
132
|
+
|
133
|
+
writer.puts "public enum #{java_name} implements NativeEnum {"
|
134
|
+
writer.indent do
|
135
|
+
writer.write_array @constants, "," do |constant|
|
136
|
+
"#{constant[:name].to_java_constant}(#{constant[:value]})"
|
137
|
+
end
|
138
|
+
writer.puts ";"
|
139
|
+
|
140
|
+
writer.puts "", "private int nativeInt;", "", "private #{java_name}(int nativeInt) {", " this.nativeInt = nativeInt;", "}", "", "@Override", "public int toNativeInt() {", " return nativeInt;", "}"
|
141
|
+
end
|
142
|
+
writer.puts "}", ""
|
143
|
+
end
|
144
|
+
|
145
|
+
def java_name
|
146
|
+
@java_name ||= @name.to_java_classname
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class StructOrUnion
|
151
|
+
def write_java(writer)
|
152
|
+
@fields.each do |field|
|
153
|
+
field[:symbol] = field[:name].to_java_downcase
|
154
|
+
field[:type_data] = @generator.to_java_type field[:type]
|
155
|
+
end
|
156
|
+
|
157
|
+
writer.comment do
|
158
|
+
writer.write_description @comment
|
159
|
+
unless @fields.empty?
|
160
|
+
writer.puts "", "= Fields:"
|
161
|
+
@fields.each do |field|
|
162
|
+
writer.puts "#{field[:symbol]} ::"
|
163
|
+
writer.write_description field[:comment], false, " (#{field[:type_data][:description]}) ", " "
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
writer.puts "public static class #{java_name} extends #{@is_union ? 'Union' : (@fields.empty? ? 'PointerType' : 'Structure')} {"
|
169
|
+
writer.indent do
|
170
|
+
@fields.each do |field|
|
171
|
+
writer.puts "public #{field[:type_data][:jna_type]} #{field[:symbol]};"
|
172
|
+
end
|
173
|
+
writer.puts "// hidden structure" if @fields.empty?
|
174
|
+
end
|
175
|
+
writer.puts "}", ""
|
176
|
+
|
177
|
+
@written = true
|
178
|
+
end
|
179
|
+
|
180
|
+
def java_name
|
181
|
+
@java_name ||= @name.to_java_classname
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class FunctionOrCallback
|
186
|
+
def write_java(writer)
|
187
|
+
return if @is_callback # not yet supported
|
188
|
+
|
189
|
+
@parameters.each do |parameter|
|
190
|
+
parameter[:type_data] = @generator.to_java_type parameter[:type], parameter[:is_array]
|
191
|
+
parameter[:java_name] = !parameter[:name].empty? ? parameter[:name].to_java_downcase : parameter[:type_data][:parameter_name]
|
192
|
+
parameter[:description] = []
|
193
|
+
end
|
194
|
+
return_type_data = @generator.to_java_type @return_type
|
195
|
+
|
196
|
+
function_description = []
|
197
|
+
return_value_description = []
|
198
|
+
current_description = function_description
|
199
|
+
@comment.split("\n").map do |line|
|
200
|
+
line = writer.prepare_comment_line line
|
201
|
+
if line.gsub!(/\\param (.*?) /, '')
|
202
|
+
parameter = @parameters.find { |p| p[:name].raw == $1 }
|
203
|
+
if parameter
|
204
|
+
current_description = parameter[:description]
|
205
|
+
else
|
206
|
+
current_description << "#{$1}: "
|
207
|
+
end
|
208
|
+
end
|
209
|
+
current_description = return_value_description if line.gsub! '\\returns ', ''
|
210
|
+
current_description << line
|
211
|
+
end
|
212
|
+
|
213
|
+
writer.comment do
|
214
|
+
writer.write_description function_description
|
215
|
+
writer.puts "", "<em>This entry is only for documentation and no real method.</em>" if @is_callback
|
216
|
+
writer.puts "", "@method #{@is_callback ? "_callback_#{java_name}_" : java_name}(#{@parameters.map{ |parameter| parameter[:java_name] }.join(', ')})"
|
217
|
+
@parameters.each do |parameter|
|
218
|
+
writer.write_description parameter[:description], false, "@param [#{parameter[:type_data][:description]}] #{parameter[:java_name]} ", " "
|
219
|
+
end
|
220
|
+
writer.write_description return_value_description, false, "@return [#{return_type_data[:description]}] ", " "
|
221
|
+
writer.puts "@scope class"
|
222
|
+
end
|
223
|
+
|
224
|
+
jna_signature = "#{@parameters.map{ |parameter| "#{parameter[:type_data][:jna_type]} #{parameter[:java_name]}" }.join(', ')}"
|
225
|
+
if @is_callback
|
226
|
+
writer.puts "callback :#{java_name}, #{jna_signature}", ""
|
227
|
+
else
|
228
|
+
writer.puts "@NativeName(\"#{@name.raw}\")", "#{return_type_data[:jna_type]} #{java_name}(#{jna_signature});", ""
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def java_name
|
233
|
+
@java_name ||= @name.to_java_downcase
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
class Constant
|
238
|
+
def write_java(writer)
|
239
|
+
writer.puts "public static int #{@name.to_java_constant} = #{@value};", ""
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|