-
Notifications
You must be signed in to change notification settings - Fork 6
Add Go Bindings generation #9
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
Closed
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
# | ||
# Copyright © 2024, Oracle and/or its affiliates | ||
# | ||
# SPDX-License-Identifier: MIT | ||
|
||
from .common import BasicJinjaRender | ||
from .lang import language, TEMPLATE_DIR | ||
|
||
import re | ||
|
||
DATATYPES = { | ||
"http://www.w3.org/2001/XMLSchema#string": "string", | ||
"http://www.w3.org/2001/XMLSchema#anyURI": "string", | ||
"http://www.w3.org/2001/XMLSchema#integer": "int", | ||
"http://www.w3.org/2001/XMLSchema#positiveInteger": "PInt", | ||
"http://www.w3.org/2001/XMLSchema#nonNegativeInteger": "uint", | ||
"http://www.w3.org/2001/XMLSchema#boolean": "bool", | ||
"http://www.w3.org/2001/XMLSchema#decimal": "float64", | ||
"http://www.w3.org/2001/XMLSchema#dateTime": "DateTime", | ||
"http://www.w3.org/2001/XMLSchema#dateTimeStamp": "DateTimeStamp", | ||
} | ||
|
||
|
||
def upper_first(string): | ||
# upper_first will capitalize the string | ||
return string[0].upper() + string[1:] | ||
|
||
|
||
def lower_first(string): | ||
# lower_first sets the first character of a string to lower case | ||
return string[0].lower() + string[1:] | ||
|
||
|
||
def type_name(clsname): | ||
# type_name converts the class name into an exportable go type name | ||
return upper_first(''.join(clsname).replace('_','')) | ||
|
||
|
||
def interface_method(propname): | ||
# returns an interface method name | ||
# The interface method names are capitalized so they can be exported | ||
parts = propname.split('_') | ||
parts[0] = upper_first(parts[0]) | ||
return ''.join(parts) | ||
|
||
def struct_name(clsname): | ||
# Go structs are only used when a class is a concrete class | ||
return lower_first(type_name(clsname)) + "Impl" | ||
|
||
|
||
def struct_prop_name(propname): | ||
# All properties in a Go struct are non-exportable | ||
return propname.replace('_','') | ||
|
||
|
||
def setter_prop_type(prop): | ||
typ = prop_type(prop) | ||
return typ.replace('[]', "...") | ||
|
||
|
||
def struct_prop(prop): | ||
return struct_prop_name(prop) + ' ' + prop_type(prop) | ||
< 10000 /span> |
||
|
||
def interface_getter(prop): | ||
return type_name(prop.varname) + '() ' + prop_type(prop) | ||
|
||
|
||
def interface_setter(prop): | ||
return "Set" + type_name(prop.varname) + '(' + setter_prop_type(prop) + ') error' | ||
|
||
|
||
def struct_getter(cls, prop): | ||
return 'func (o *' + struct_name(cls) + ') ' + type_name(prop.varname) + '() ' + prop_type(prop) + '{\n' \ | ||
+ ' return o.' + struct_prop_name(prop) + '\n' \ | ||
+ '}' | ||
|
||
|
||
def struct_setter(cls, prop): | ||
return 'func (o *' + struct_name(cls) + ') Set' + type_name(prop.varname) + '(v ' + setter_prop_type(prop) + ') error{\n' \ | ||
+ ' o.' + struct_prop_name(prop) + ' = v\n' \ | ||
+ ' return nil\n' \ | ||
+ '}' | ||
|
||
|
||
def comment(indent_with, identifier, text): | ||
if text.lower().startswith(identifier.lower()): | ||
text = identifier + " " + text[len(identifier):] | ||
|
||
return indent(indent_with, text) | ||
|
||
def parent_has_prop(classes, cls, prop): | ||
for parent_id in cls.parent_ids: | ||
parent = classes.get(parent_id) | ||
for p in parent.properties: | ||
if p.varname == prop.varname: | ||
return True | ||
if parent_has_prop(classes, parent, prop): | ||
return True | ||
|
||
return False | ||
|
||
|
||
def include_prop(classes, cls, prop): | ||
return not parent_has_prop(classes, cls, prop) | ||
|
||
|
||
|
||
|
||
def interface_name(cls): | ||
return type_name(cls.clsname) | ||
|
||
|
||
|
||
|
||
def indent(indent_with, str): | ||
parts = re.split("\n", str) | ||
return indent_with + ("\n"+indent_with).join(parts) | ||
|
||
|
||
@language("golang") | ||
class GolangRender(BasicJinjaRender): | ||
HELP = "Go Language Bindings" | ||
|
||
def __init__(self, args): | ||
super().__init__(args, TEMPLATE_DIR / "golang.j2") | ||
self.__render_args = { | ||
"module": args.module, | ||
} | ||
|
||
@classmethod | ||
def get_arguments(cls, parser): | ||
super().get_arguments(parser) | ||
parser.add_argument("--module", help="Go module name") | ||
|
||
def get_extra_env(self): | ||
return { | ||
"type_name": type_name, | ||
"interface_method": interface_method, | ||
"struct_prop_name": struct_prop_name, | ||
"struct_name": struct_name, | ||
"struct_getter": struct_getter, | ||
"struct_setter": struct_setter, | ||
"interface_name": interface_name, | ||
"interface_getter": interface_getter, | ||
"interface_setter": interface_setter, | ||
"include_prop": include_prop, | ||
"indent": indent, | ||
"comment": comment, | ||
"DATATYPES": DATATYPES, | ||
} | ||
|
||
def get_additional_render_args(self): | ||
return self.__render_args |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// package spdx_v3_0 provides structs for SPDX 3.0 | ||
// | ||
// {{ disclaimer }} | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
{# helpful macros #} | ||
|
||
{%- macro array(prop) %} | ||
{%- if prop.max_count and prop.max_count >= 1 -%} | ||
[] | ||
{%- endif -%} | ||
{%- endmacro %} | ||
|
||
{%- macro many(prop) %} | ||
{%- if prop.max_count and prop.max_count >= 1 -%} | ||
... | ||
{%- endif -%} | ||
{%- endmacro %} | ||
|
||
{%- macro prop_type(prop) %} | ||
{%- if prop.class_id -%} | ||
{{ type_name(classes.get(prop.class_id).clsname) }} | ||
{%- else -%} | ||
{{ DATATYPES[prop.datatype] }} | ||
{%- endif %} | ||
{%- endmacro %} | ||
|
||
{%- macro namedind(class) %} | ||
type {{ type_name(class.clsname) }} struct { | ||
ObjRef {{ type_name(class.clsname) }}Ref | ||
} | ||
{%- endmacro %} | ||
|
||
{%- macro interface(class) %} | ||
type {{ type_name(class.clsname) }} interface { | ||
{% for parent in class.parent_ids %} | ||
{{ type_name(classes.get(parent).clsname) }} | ||
{% endfor %} | ||
{% for prop in class.properties %} | ||
{{ interface_method(prop.varname) }}() {{ array(prop) }}{{ prop_type(prop) }} | ||
Set{{ interface_method(prop.varname) }}(p {{ many(prop) }}{{ prop_type(prop) }}) error | ||
{% endfor %} | ||
} | ||
{%- endmacro %} | ||
|
||
{%- macro struct(class) %} | ||
type {{ struct_name(class.clsname) }} struct { | ||
{% for parent in class.parent_ids %} | ||
//-----------{{ type_name(classes.get(parent).clsname) }}-------- | ||
{% for prop in classes.get(parent).properties %} | ||
{{ struct_prop_name(prop.varname) }} {{ array(prop) }}{{ prop_type(prop) }} | ||
{% endfor %} | ||
{% endfor %} | ||
{% if not class.named_individuals %} | ||
{% for prop in class.properties %} | ||
{{ struct_prop_name(prop.varname) }} {{ array(prop) }}{{ prop_type(prop) }} | ||
{% endfor %} | ||
{% endif %} | ||
} | ||
{%- endmacro %} | ||
|
||
{%- macro constructor(class) %} | ||
func New{{ type_name(class.clsname) }}() {{ type_name(class.clsname) }} { | ||
return &{{ struct_name(class.clsname) }}{} | ||
} | ||
{%- endmacro %} | ||
|
||
{%- macro func(class) %} | ||
{%- for prop in class.properties %} | ||
func (o * {{ type_name(class.clsname) }}) {{ interface_method(prop.varname) }}() {{ prop_type(prop) }}{ | ||
return o.{{ struct_prop_name(prop.varname) }} | ||
} | ||
|
||
func (o *{{ type_name(class.clsname) }}) Set{{ interface_method(prop.varname) }}(v {{ prop_type(prop) }}) error { | ||
o.{{ struct_prop_name(prop.varname) }} = v | ||
return nil | ||
} | ||
{%- endfor %} | ||
{%- endmacro %} | ||
|
||
{# go file content #} | ||
package spdx_v{{ module }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Remember that shacl2code is not (intended) to be specific to SPDX :) |
||
|
||
// NAMED INDIVIDUALS | ||
|
||
{%- for class in classes %} | ||
{%- if class.named_individuals %} | ||
type {{ type_name(class.clsname) }}Ref string | ||
var ( | ||
{%- for ind in class.named_individuals %} | ||
{{ type_name(class.clsname) }}{{ ind.varname }} {{ type_name(class.clsname) }}Ref = "{{ ind._id }}" | ||
{%- endfor %} | ||
) | ||
{%- endif %} | ||
{%- endfor %} | ||
|
||
// INTERFACES | ||
|
||
{% for class in classes %} | ||
{% if class.named_individuals %} | ||
{{ namedind(class) }} | ||
{% else %} | ||
{{ interface(class) }} | ||
{% endif %} | ||
{% endfor %} | ||
|
||
// STRUCTS AND CONSTRUCTORS | ||
|
||
{% for class in concrete_classes %} | ||
{{ struct(class) }} | ||
{{ constructor(class) }} | ||
{% endfor %} | ||
|
||
// IMPLEMENTATIONS | ||
|
||
{% for class in concrete_classes %} | ||
{{ func(class) }} | ||
{% endfor %} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably want
required=True
to make this option required, since the option is required to generate correct bindings