Bug 156168 - [model] type separator is ignored in BinaryType.getFullyQualifiedName(enclosingTypeSeparator)
Summary: [model] type separator is ignored in BinaryType.getFullyQualifiedName(enclosi...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P2 major with 1 vote (vote)
Target Milestone: 3.4 M6   Edit
Assignee: Jerome Lanneluc CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 182179 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-09-05 04:57 EDT by jan.koehnlein CLA
Modified: 2008-03-25 08:23 EDT (History)
6 users (show)

See Also:


Attachments
Fix (3.57 KB, patch)
2007-10-12 12:51 EDT, Markus Keller CLA
no flags Details | Diff
Proposed fix and regression tests (13.89 KB, patch)
2008-03-11 10:33 EDT, Jerome Lanneluc CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description jan.koehnlein CLA 2006-09-05 04:57:12 EDT
Given 

package p;
public class X {
   class Y {
   }
}

as binary (e.g. in a JAR). 

Calling getFullyQualifiedName('.') on a the BinaryType describing Y returns 
  p.X$Y 
instead of 
  p.X.Y
as the documentation says
Comment 1 Frederic Fusier CLA 2006-10-04 10:43:28 EDT
Problem is in NameMember.getTypeQualifiedName(char, boolean) which does not replace  '$' with enclosingTypeSeparator for CLASS_FILE when indexOf('$') != -1...
Comment 2 Frederic Fusier CLA 2006-10-06 11:30:11 EDT
I read again the documentation:
/**
 * Returns the type-qualified name of this type, 
 * including qualification for any enclosing types,
 * but not including package qualification.
 * For source types, this consists of the simple names of any enclosing types, 
 * separated by <code>enclosingTypeSeparator</code>, followed by the 
 * simple name of this type  or the occurence count of this type if it is anonymous.
 * For binary types, this is the name of the class file without the ".class" suffix.
 * 
 * For example:
 * <ul>
 * <li>the type qualified name of a class B defined as a member of a class A
 *     using the '.' separator is "A.B"</li>
 * <li>the type qualified name of a class B defined as a member of a class A
 *     using the '$' separator is "A$B"</li>
 * <li>the type qualified name of a binary type whose class file is A$B.class
 *     using the '.' separator is "A$B"</li>
 * <li>the type qualified name of a binary type whose class file is A$B.class
 *     using the '$' separator is "A$B"</li>
 * <li>the type qualified name of an anonymous binary type whose class file is A$1.class
 *     using the '.' separator is "A$1"</li>
 * </ul>
 *
 * This is a handle-only method.
 * 
 * @param enclosingTypeSeparator the specified enclosing type separator
 * @return the type-qualified name of this type
 * @since 2.0
 */
String getTypeQualifiedName(char enclosingTypeSeparator);

The important point is:
For binary types, this is the name of the class file without the ".class" suffix.
...
 * <li>the type qualified name of a binary type whose class file is A$B.class
 *     using the '$' separator is "A$B"</li>

So, we behave as documented => close as INVALID
Comment 3 Frederic Fusier CLA 2006-12-02 06:16:06 EST
*** Bug 165849 has been marked as a duplicate of this bug. ***
Comment 4 Frederic Fusier CLA 2007-04-16 12:09:50 EDT
*** Bug 182179 has been marked as a duplicate of this bug. ***
Comment 5 Markus Keller CLA 2007-10-12 12:49:06 EDT
Sorry, it's unbelievable, but I have to reopen this.

From HEAD of IType:

/**
[..]
 * This is the name of the package, followed by <code>'.'</code>,
 * followed by the type-qualified name using the
 * <code>enclosingTypeSeparator</code>.
[..]
 * <li>the fully qualified name of a binary type whose class file is
 *     x/y/A$B.class using the '.' separator is "x.y.A.B"</li>
[..]
 */
String getFullyQualifiedName(char enclosingTypeSeparator);


/**
[..]
 * For binary types, this is the name of the class file without the ".class" suffix.
[..]
 * <li>the type qualified name of a binary type whose class file is A$B.class
 *     using the '.' separator is "A$B"</li>
[..]
 */
String getTypeQualifiedName(char enclosingTypeSeparator);

Javadoc of getTypeQualifiedName(char) was changed on 2005-12-14 from
 * <li>the type qualified name of a binary type whose class file is A$B.class
 *     using the '.' separator is "A.B"</li>

==> The definition of #getFullyQualifiedName(char) is inconsistent: It says it uses the type-qualified name (which would result in "x.y.A$B"), but its example says "x.y.A.B". The implementation has probably been to return "x.y.A$B" for a long time, so I think the only action we can take now is to finally make the specification of #getFullyQualifiedName(char) match the implementation.
Comment 6 Markus Keller CLA 2007-10-12 12:51:39 EDT
Created attachment 80247 [details]
Fix

Fix with big warnings for the unexpected behavior of this API. We definitely need to make sure clients are made aware of the deficiencies of these methods.
Comment 7 Frederic Fusier CLA 2007-10-15 03:51:27 EDT
Assign to Jerome who has the most valuable feedback on these API methods to decide what to do finally on this long standing issue... (see also bug 120640)
Comment 8 Martin Aeschlimann CLA 2007-10-15 05:13:03 EDT
Can't we just fix the behavior to what the user expects here:
No $, only '.'.

Even if it involves some dirty tricks in the implementation, but it would jut make  all users life easier and less complicated. This issue is a source of reoccurring bugs.
At the moment we in JDT UI have a utility method to wrap and fix getFullyQualifiedName. 

The search engine was always capable of returning the full information (package name, enclosing type names, type name). We need this for correctness also there. See discussion in bug 182179 comment 7.
Comment 9 Jerome Lanneluc CLA 2007-10-15 06:04:40 EDT
Would that be ok if the fully qualified name of a binary type named A$B (as in 
  package x.y;
  public class A$B {
  }
) were "x.y.A.B" ? 

Note that since getFullyQualifiedName(..) is a handle only method we cannot open the underlying .cass file to get the information.
Comment 10 Markus Keller CLA 2007-10-15 07:11:17 EDT
(In reply to comment #9)
If there's no more information, the correct assumption would indeed be that A$B.class comes from a nested binary type

See JLS3 3.8: "The $ character should be used only in mechanically generated source code or, rarely, to access preexisting names on legacy systems."
and JLS3 13.1: "The binary name of a member type consists of the binary name of its immediately enclosing type, followed by $, followed by the simple name of the member."
Comment 11 Kevin Bracey CLA 2007-11-01 13:46:28 EDT
I've just plowed into this bug while looking into links in the Javadoc view. Ouch, ouch, ouch.

This is horrible. BinaryType is not fulfulling the specification of IType, and is behaving inconsistently with SourceType.

Please fix.

The concern about literal $ in class names seems silly - if the implementation can't resolve the ambiguity, then it can't resolve the ambiguity. But why not go for the option that will be correct 99.9% of the time, rather than the 0.1% option?
Comment 12 Jerome Lanneluc CLA 2008-03-11 10:33:13 EDT
Created attachment 92167 [details]
Proposed fix and regression tests
Comment 13 Jerome Lanneluc CLA 2008-03-12 05:31:02 EDT
Fix and tests released for 3.4M6
Comment 14 Jerome Lanneluc CLA 2008-03-12 05:36:56 EDT
*** Bug 182179 has been marked as a duplicate of this bug. ***
Comment 15 David Audel CLA 2008-03-25 08:23:46 EDT
Verified for 3.4M6 using build I20080324-1300.