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

Java: multiple initializers get same id. #9418

Open
Stewori opened this issue Jun 24, 2022 · 3 comments
Open

Java: multiple initializers get same id. #9418

Stewori opened this issue Jun 24, 2022 · 3 comments
Labels

Comments

@Stewori
Copy link

Stewori commented Jun 24, 2022

Describe the bug
Processing Java code

public class Test
{
  /**Text1*/
  static {int a = 1;}

  /**Text2*/
  static {int b = 2;}
}

results in the following xml snippet:

      <memberdef kind="function" id="classTest_1ae100a188acb0137873a6e58761599318" prot="package" static="yes" const="no" explicit="no" inline="yes" virt="non-virtual">
        <type></type>
        <definition>Test.[static initializer]</definition>
        <argsstring></argsstring>
        <name>[static initializer]</name>
        <qualifiedname>Test.[static initializer]</qualifiedname>
        <briefdescription>
        </briefdescription>
        <detaileddescription>
<para>Text1 </para>
        </detaileddescription>
        <inbodydescription>
        </inbodydescription>
        <location file="Test.java" line="1" column="1"/>
      </memberdef>
      <memberdef kind="function" id="classTest_1ae100a188acb0137873a6e58761599318" prot="package" static="yes" const="no" explicit="no" inline="yes" virt="non-virtual">
        <type></type>
        <definition>Test.[static initializer]</definition>
        <argsstring></argsstring>
        <name>[static initializer]</name>
        <qualifiedname>Test.[static initializer]</qualifiedname>
        <briefdescription>
        </briefdescription>
        <detaileddescription>
<para>Text2 </para>
        </detaileddescription>
        <inbodydescription>
        </inbodydescription>
        <location file="Test.java" line="1" column="1"/>
      </memberdef>

Note that the initializers get the same id. I think they should have different ids and this causes problems for me because it violates the natural assumption that ids should be unique. Note that Doxygen indeed does distinguish the members internally as is proven by the doc text. OTOH, the second location entry is wrong again. Also note that for some reason, no initializer sections are created in xml for this example.
The same issue occurs if there are two instance initializers, i.e. without static. It does not occur if there is one instance initializer and one static.

Expected behavior
I expect that the resulting code snippet would use distinct and unique ids for the two members and that correct initializer and location xml entries are generated.

To Reproduce
Find a Java file and doxygen config attached. The issue is demonstrated like mentioned above.
After running doxygen on the example, the files in the subfolder xml contain the snippet shown above.
issue_multiple_initializers.zip

Version
Tested with doxygen release 1.9.3.1:

/blah/doxygen/build/bin/doxygen -v
1.9.3.1

Unfortunately, I am currently not able to build newer doxygen versions.

lsb_release -a:

LSB Version:	core-9.20160110ubuntu0.2-amd64:core-9.20160110ubuntu0.2-noarch:security-9.20160110ubuntu0.2-amd64:security-9.20160110ubuntu0.2-noarch
Distributor ID:	LinuxMint
Description:	Linux Mint 18 Sarah
Release:	18
Codename:	sarah

Additional context
TBH I did not check for duplicates. Please excuse if this is a known issue.
Also, as mentioned above, I am currently not able to build recent doxygen versions. Please excuse if the issue is already fixed.

@albert-github
Copy link
Collaborator

In the HTML output I don't see the a and b at all, even when I set EXTRACT_STATIC = YES. After setting all EXTRACT_... = YES (didn't check which one I needed) I see some information about the static initializers.
The result looks like:

image

we see that there is still no mention of a or b and that both static initializers are given just as :

image

and in the detailed section as:

image

so it looks like the name is not caught at all.

You also mentioned:

The same issue occurs if there are two instance initializers, i.e. without static. It does not occur if there is one instance initializer and one static.

  • I think here the same problem occurs (i.e. name missing)
  • can you give an example of these 2 cases as well (so I have valid Java code for those test cases as well).

@albert-github
Copy link
Collaborator

Some questions Regarding the static initializers, to get some specifications a bit clearer:

  1. The construct
    static { int a = 1; }
    
    is equal to
    static int a = 1;
    
  2. The construct
    static {
      int a = 1;
      int b = 2;
    }
    
    is equal to:
    static int a = 1;
    static int b = 1;
    
  3. The construct
    /**Text1*/
    static { int a = 1; }
    
    is equal to
    static {
      /**Text1*/
      int a = 1;
    }
    
  4. The construct
    /**Text1*/
    static {
      int a = 1;
      int b = 2;
    }
    
    should be equal to
    static {
      /**Text1*/
      int a = 1;
      /**Text1*/
      int b = 2;
    }
    

@Stewori
Copy link
Author

Stewori commented Jul 1, 2022

No, I think none of the statements is true. I am not sure how Java handles it internally in the final result, but I know how Doxygen used to handle it and I think it is much the same as how Java's compiler's AST represents it.

static { int a = 1; } creates a static member called [static initializer]. a would not become a member at all and exists only locally within the {...} block. In xml, [static initializer] may have an <initializer> tag that would contain the text { int a = 1;}.
Much like for the code int a = 1; which would create a member a, the initializer tag would contain = 1 (static int a = 1 is the same except that in xml, there is the property static=yes).

static {
  /**Text1*/
  int a = 1;
  /**Text1*/
  int b = 2;
}

In such examples, the docstrings should be ignored (and I think that is the way how Doxygen already does it). It would be like having docstrings for local variables like inside a method. Neither Javadoc nor Doxygen supports this. In general, Java initializers are like methods that run at class initialization time. Maybe my example was misleading because I only put declarations in there. There can actually be arbitrary code; it is not just a declarative section.

The main issue is really that multiple initializers get the same ID. Everything else in this example works as expected. I noticed that Doxygen does not always create an <initializer> tag for Java initializers in general, so that is probably a separate issue anyway. I do not really care much about the <initializer> tag, I just mentioned its absence for completeness.
An example where I observed an <initializer> tag being created for a [static initializer] member is the OP of #9417 . I did not post that part of xml, but it is in the attachment.

      <memberdef kind="variable" id="classTest_1a570c74fef59443512a796edd0db62e81" prot="package" static="yes" mutable="no">
        <type></type>
        <definition>Test.static</definition>
        <argsstring></argsstring>
        <name>static</name>
        <qualifiedname>Test.static</qualifiedname>
        <initializer>{
          a.trim()</initializer>
        <briefdescription>
        </briefdescription>
        <detaileddescription>
        </detaileddescription>
        <inbodydescription>
        </inbodydescription>
        <location file="Test.java" line="4" column="3" bodyfile="Test.java" bodystart="4" bodyend="-1"/>
      </memberdef>

The <initializer> tag is incomplete though. It should be {a.trim(); b.trim();}. Maybe it is part of that issue that the tag is created at all and normal Doxygen behavior is not to create <initializer> tags for [(static) initializer] members.

An example with non-static initializers is simply the OP-example with the word static removed entirely. You will get again two members, this time called [initializer]. They are clearly distinct (in xml), as can be seen by their <detaileddescription>. But they have the same id value, which violates the promise of ids being unique.

public class Test
{
  /**Text1*/
  {int a = 1;}

  /**Text2*/
  {int b = 2;}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants