Skip to content

Commit

Permalink
Annotations for union's discriminators (#148)
Browse files Browse the repository at this point in the history
* Refs #21222. Add default annotation to union's discriminator

Signed-off-by: Ricardo González Moreno <[email protected]>

* Refs #21222. Get default integer discriminator value from max

Signed-off-by: Ricardo González Moreno <[email protected]>

* Refs #21222. Documentation

Signed-off-by: Ricardo González Moreno <[email protected]>

* Refs #21222. Apply suggestions

Signed-off-by: Ricardo González Moreno <[email protected]>

* Refs #21222. Apply suggestion

Signed-off-by: Ricardo González Moreno <[email protected]>

---------

Signed-off-by: Ricardo González Moreno <[email protected]>
  • Loading branch information
richiware authored Jul 8, 2024
1 parent 97ed0b3 commit 03fbf21
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 11 deletions.
9 changes: 8 additions & 1 deletion src/main/antlr/com/eprosima/idl/parser/grammar/IDL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,7 @@ union_type [Vector<Annotation> annotations, ArrayList<Definition> defs] returns
UnionTypeCode unionTP = null;
TemplateGroup unionTemplates = null;
Boolean fw_decl = false;
ArrayList<Annotation> discriminator_annotations = new ArrayList<Annotation>();
}
: KW_UNION
identifier
Expand Down Expand Up @@ -1732,7 +1733,7 @@ union_type [Vector<Annotation> annotations, ArrayList<Definition> defs] returns
}
}
}
KW_SWITCH LEFT_BRACKET switch_type_spec { dist_type=$switch_type_spec.typecode; } RIGHT_BRACKET
KW_SWITCH LEFT_BRACKET (annotation_appl { discriminator_annotations.add($annotation_appl.annotation); })? switch_type_spec { dist_type=$switch_type_spec.typecode; } RIGHT_BRACKET
{
// TODO Check supported types for discriminator: long, enumeration, etc...
if (fw_decl)
Expand All @@ -1753,6 +1754,12 @@ union_type [Vector<Annotation> annotations, ArrayList<Definition> defs] returns
}
unionTP.setDefined();

// Set discriminator annotations.
for(Annotation annotation : discriminator_annotations)
{
unionTP.getDiscriminator().addAnnotation(ctx, annotation);
}

// Apply annotations to the TypeCode
if (null != annotations)
{
Expand Down
53 changes: 46 additions & 7 deletions src/main/java/com/eprosima/idl/generator/manager/TemplateUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,41 @@ public static void find_and_set_default_discriminator_value(ArrayList<Definition
disc_type.getKind() == Kind.KIND_CHAR ||
disc_type.getKind() == Kind.KIND_WCHAR)
{
long dvalue = -1;
long default_discriminator_value = -1;
long minimum_valid_value = -1;

// For primitive types, if the default case was not defined, use the highest unused value as the
// implicit default value.
switch (disc_type.getKind())
{
case Kind.KIND_OCTET:
case Kind.KIND_INT8:
case Kind.KIND_UINT8:
case Kind.KIND_CHAR:
default_discriminator_value = Byte.MAX_VALUE;
minimum_valid_value = Byte.MIN_VALUE;
break;
case Kind.KIND_SHORT:
case Kind.KIND_USHORT:
case Kind.KIND_WCHAR:
default_discriminator_value = Short.MAX_VALUE;
minimum_valid_value = Short.MIN_VALUE;
break;
case Kind.KIND_LONG:
case Kind.KIND_ULONG:
default_discriminator_value = Integer.MAX_VALUE;
minimum_valid_value = Integer.MIN_VALUE;
break;
default:
default_discriminator_value = Long.MAX_VALUE;
minimum_valid_value = Long.MIN_VALUE;
}

boolean found = true;
List<Member> list = new ArrayList<Member>(members);

do
{
++dvalue;
found = false;

for(Member member : list)
Expand Down Expand Up @@ -109,21 +137,32 @@ public static void find_and_set_default_discriminator_value(ArrayList<Definition
}
}

if(dvalue == value)
if(default_discriminator_value == value)
{
found = true;
break;
}
}
}

if(found) break;
if(found)
{
// Possible default implicit value used. Try with the next lower value.
--default_discriminator_value;
break;
}
}
}
while(found);
while(found && default_discriminator_value >= minimum_valid_value);

if (found)
{
// All values were used. Using value 0 as default implicit value.
default_discriminator_value = 0;
}

union_type.setDefaultvalue(Long.toString(dvalue));
union_type.setJavaDefaultvalue(Long.toString(dvalue));
union_type.setDefaultvalue(Long.toString(default_discriminator_value));
union_type.setJavaDefaultvalue(Long.toString(default_discriminator_value));
}
else if(disc_type.getKind() == Kind.KIND_BOOLEAN)
{
Expand Down
88 changes: 85 additions & 3 deletions src/main/java/com/eprosima/idl/parser/typecode/UnionTypeCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,12 @@ public int addMember(
List<String> labels = null;
List<String> javalabels = null;

if (Kind.KIND_ENUM == discriminator_.getTypecode().getKind() ||
Kind.KIND_BITMASK == discriminator_.getTypecode().getKind())
TypeCode discriminator_typecode = discriminator_.getTypecode();

if (Kind.KIND_ENUM == discriminator_typecode.getKind() ||
Kind.KIND_BITMASK == discriminator_typecode.getKind())
{
MemberedTypeCode enum_type = (MemberedTypeCode)discriminator_.getTypecode();
MemberedTypeCode enum_type = (MemberedTypeCode)discriminator_typecode;
labels = new ArrayList<String>();
javalabels = new ArrayList<String>();

Expand All @@ -121,6 +123,37 @@ public int addMember(
javalabels = internal_labels;
}

// Checks the discriminator has the @default annotation. In that case check the union's member has a label with
// the @default annotation value and if they match store the union's member index.
try
{
if (discriminator_.isAnnotationDefault())
{
String default_value = discriminator_.getAnnotationDefaultValue();

for (String label : labels)
{
if (label.equals(default_value))
{
if (m_defaultannotated_index == -1)
{
m_defaultannotated_index = getMembers().size();
}
else
{
// Default value matches with more than one member.
return -2;
}
}
}
}
}
catch(RuntimeGenerationException ex)
{
// Never enter here because we check previously using isAnnotationDefault().
}


member.setLabels(labels);
member.setJavaLabels(javalabels);

Expand All @@ -133,6 +166,26 @@ public int addMember(
return 0;
}

/*!
* @ingroup api_for_stg
* @brief This function returns the union's member which contains a label that matches with discriminator's
* @default annotation. If no one then return \b null.
* @return The union's member that passes the conditions or \b null value.
*/
public Member getDefaultAnnotatedMember() throws RuntimeGenerationException
{
if (m_defaultannotated_index != -1)
{
return getMembers().get(m_defaultannotated_index);
}
else if (discriminator_.isAnnotationDefault())
{
throw new RuntimeGenerationException("UnionTypeCode::getDefaultAnnotatedMember(): Discriminator has a default value but that value was not found in label cases");
}

return null;
}

public Member getDefaultMember()
{
if (m_defaultindex != -1)
Expand Down Expand Up @@ -217,6 +270,29 @@ public void setJavaDefaultvalue(
m_javaDefaultValue = value;
}

/*!
* @ingroup api_for_stg
* @brief This function returns the discriminator's @default annotation value as string. If annotation was not
* defined, returns \b null.
* @return The discriminator's @default annotation value or \b null if annotation was not defined
*/
public String getDefaultAnnotatedValue()
{
try
{
if (discriminator_.isAnnotationDefault())
{
return discriminator_.getAnnotationDefaultValue();
}
}
catch(RuntimeGenerationException ex)
{
// Never enter here because we check previously using isAnnotationDefault().
}

return null;
}

// Used in stringtemplates
public String getDefaultvalue()
{
Expand Down Expand Up @@ -278,6 +354,12 @@ public void addAnnotation(

private int m_defaultindex = -1;

/*!
* Stores the index of the union's member which contains a label that matches with the discriminator's @default
* annotation.
*/
private int m_defaultannotated_index = -1;

private String m_defaultValue = null;

private String m_javaDefaultValue = null;
Expand Down

0 comments on commit 03fbf21

Please sign in to comment.