Subject: Re: bug#72402: 28.2; Etags does not parse correctly Java source code

From: Eli Zaretskii <[email-masked]>
Date: Thu, 01 Aug 2024 11:16:31 +0300

> From: Daniel Głowacki <[email-masked]>
> Date: Wed, 31 Jul 2024 17:27:33 +0200
> 
> I have found a bug while using 'etags' program for parsing Java files.
> Some of Java files are not parsed as they should be. Important parts
> of the code is missing.
> 
> Some example below:
> ===================
> JAVA VERSION: OpendJDK version 22
> SOURCE FILE: $(JAVA_HOME)/lib/src/java.base/java/util/HashMap.java
> 
> ...
> 
> public class HashMap<K,V> extends AbstractMap<K,V>
>     implements Map<K,V>, Cloneable, Serializable {
> 
>     @java.io.Serial
>     private static final long serialVersionUID = 362498820763181265L;
> 
> ...
> 
> 'TAGS' FILE CREATED BY 'ETAGS':
> 
> ...
> 
> src/java.base/java/util/HashMap.java,2267
>     implements Map<Map%1140,6932
>     implements Map<K,V>, Cloneable,140,6932
>     final class KeySet 988,39333
>         public final int size(989,39381
>         public final void clear(990,39446
>         public final Iterator<K> iterator(991,39520
>         public final boolean contains(992,39598
>         public final boolean remove(993,39673
>         public final Spliterator<K> spliterator(996,39807
>         public Object[] toArray(1000,39938
>         public <T> T[] toArray(1004,40035
>         public final void forEach(1008,40135
>     final class Values 1048,41686
>         public final int size(1049,41741
>         public final void clear(1050,41806
>         public final Iterator<V> iterator(1051,41880
>         public final boolean contains(1052,41960
>         public final Spliterator<V> spliterator(1053,42037
>         public Object[] toArray(1057,42170
>         public <T> T[] toArray(1061,42269
>         public final void forEach(1065,42371
>     final class EntrySet 1102,43948
>         public final int size(1103,44011
>         public final void clear(1104,44076
>         public final Iterator<Map.Entry<K,V>> iterator(1105,44150
>         public final boolean contains(1108,44259
>         public final boolean remove(1115,44546
>         public final Spliterator<Map.Entry<K,V>> spliterator(1123,44858
>         public final void forEach(1126,45003
>     private static final class UnsafeHolder 1567,60383
>         private UnsafeHolder(1568,60429
>         static void putLoadFactor(1573,60725
>     abstract class HashIterator 1581,60945
>         Node<Node%11582,60979
>         Node<K,V> next;1582,60979
>         Node<Node%11583,61034
>         Node<K,V> current;1583,61034
>         int expectedModCount;1584,61082
>         int index;1585,61130
>         HashIterator(1587,61178
>         public final boolean hasNext(1597,61508
>         final Node<Node%11601,61593
>         final Node<K,V> nextNode(1601,61593
>         public final void remove(1614,62079
>     final class KeyIterator 1626,62481
>         public final K next(1628,62563
>     final class ValueIterator 1631,62627
>         public final V next(1633,62711
>     final class EntryIterator 1636,62777
>         public final Map.Entry<Entry%11638,62874
>         public final Map.Entry<K,V> next(1638,62874
> 
> ....
> 
> The class declaration of HashMap is missing. It works for other files,
> e.g. ArrayJava.java

Hmm... "etags --help" doesn't seem to indicate that classes are
tagged:

  etags --help --lang=c --lang=c++ --lang=java
  In C code, any C function or typedef is a tag, and so are
  definitions of 'struct', 'union' and 'enum'.  '#define' macro
  definitions and 'enum' constants are tags unless you specify
  '--no-defines'.  Global variables are tags unless you specify
  '--no-globals' and so are struct members unless you specify
  '--no-members'.  Use of '--no-globals', '--no-defines' and
  '--no-members' can make the tags table file much smaller.
  You can tag function declarations and external variables by
  using '--declarations'.

  In C++ code, all the tag constructs of C code are tagged.  (Use
  --help --lang=c --lang=c++ for full help.)
  In addition to C tags, member functions are also recognized.  Member
  variables are recognized unless you use the '--no-members' option.
  Tags for variables and functions in classes are named 'CLASS::VARIABLE'
  and 'CLASS::FUNCTION'.  'operator' definitions have tag names like
  'operator+'.

  In Java code, all the tags constructs of C and C++ code are
  tagged.  (Use --help --lang=c --lang=c++ --lang=java for full help.)

It says nothing about classes, only about class members?

Can you post a Java file which has more-or-less complete class
declarations, including the problematic one, and where some classes
are tagged while others aren't?  I'd like to try to figure out why
some are tagged, but not others, and it's hard without an example.
Please post the minimal example, to make stepping through the code
easier.

Thanks.