Skip to content

Issues with classes starting with $#671

Open
snjeza wants to merge 1 commit intoeclipse-jdt:masterfrom
snjeza:issue-670
Open

Issues with classes starting with $#671
snjeza wants to merge 1 commit intoeclipse-jdt:masterfrom
snjeza:issue-670

Conversation

@snjeza
Copy link
Contributor

@snjeza snjeza commented Jan 30, 2023

Fixes #670

Signed-off-by: Snjezana Peco snjezana.peco@redhat.com

@snjeza
Copy link
Contributor Author

snjeza commented Aug 26, 2025

@rgrunber I have rebased the PR.

@SentryMan
Copy link

Are the checks supposed to fail?

@iloveeclipse
Copy link
Member

Are the checks supposed to fail?

No. There are 3 new compiler warnings https://ci.eclipse.org/jdt/job/eclipse.jdt.core-Github/job/PR-671/5/eclipse/

@robstryker
Copy link
Contributor

@snjeza Maybe fix the NLS warning here?

"Virtual resource "+externalAnnotationPath+" cannot be used as annotationpath for project "+project.getName())); //$NON-NLS-1' //$NON-NLS-2$

Specifically, this line has $NON-NLS-1' when it shouldn't ?

@snjeza
Copy link
Contributor Author

snjeza commented Oct 31, 2025

@robstryker @iloveeclipse I have updated the PR.

@SentryMan
Copy link

The tests pass, is there anything else that needs to be done before review?

@SentryMan
Copy link

Is there some other forum that should be used to request review?

@fbricon
Copy link

fbricon commented Jan 28, 2026

@iloveeclipse @stephan-herrmann @jukzi can a JDT committer give this PR some love pretty please?

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes issues with Java classes whose names contain or start with the $ character, which were causing problems with code assistance, organize imports, search, and open type functionality.

Changes:

  • Modified dollar sign replacement logic across multiple core classes to distinguish between $ as an inner class separator versus $ as part of a legitimate class name
  • Added logic to preserve $ characters at the beginning/end of names and in consecutive sequences (e.g., $$)
  • Fixed ClassFile.getTypeName() to handle classes starting with $ correctly by changing the condition from lastDollar > -1 to lastDollar > 0

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
ClassFileMatchLocator.java Updated dollar-to-dot replacement logic for search functionality (has a critical bug)
Util.java Added getLastDotDollar() helper and updated multiple signature processing methods to preserve $ in class names
NamedMember.java Modified type name processing to preserve $ at boundaries and in consecutive sequences
NameLookup.java Updated type lookup logic for both binary and source packages to handle $ correctly
LambdaExpression.java Added isBinary() override to properly delegate to parent
ClassFile.java Fixed getTypeName() to handle classes starting with $ by changing lastDollar comparison from > -1 to > 0
BinaryType.java Changed declaring type check from lastDollar == -1 to lastDollar <= 0
Signature.java Added getLastDotDollar() helper and updated multiple signature methods to preserve $ in class names
SignatureTests.java Added comprehensive tests for classes with $ at start, end, and in consecutive sequences
ClassFileTests.java Added integration tests for fully qualified names with various $ patterns

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

} else {
// anonymous or local class file
typeName = classFileName.substring(0, classFileName.lastIndexOf('.'))/*remove .class*/.replace('$', enclosingTypeSeparator);
// see see https://github.com/eclipse-jdt/eclipse.jdt.core/pull/671
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment has a duplicate "see" - "see see https://...". Should be just "see https://...".

Suggested change
// see see https://github.com/eclipse-jdt/eclipse.jdt.core/pull/671
// see https://github.com/eclipse-jdt/eclipse.jdt.core/pull/671

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines 119 to 127
for (int i = 0, length = binaryName.length; i < length; i++) {
char c = binaryName[i];
if (c == dolar && previous != dot) {
qualifiedName[i] = dot;
} else {
qualifiedName[i] = c;
}
previous = c;
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic has a critical flaw. It only checks if the previous character is a dot to determine whether to replace '$' with '.'. This doesn't correctly handle consecutive dollar signs. For example, with input "a.b$$.C" (representing package a.b$$ with class C), the first '$' has previous='b' (not '.'), so it gets replaced with '.', making "a.b.$.C". But consecutive dollars should both be preserved as they're part of the package/class name. The logic needs to also check if the next character is a '$' before deciding to replace. Consider using a similar approach to the other files in this PR that check both isPreviousDollar and isNextDollar.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b$$ doesn't start $

Comment on lines 1994 to +2047
case C_DOLLAR:
break indexFound;
if (!isNextDollar && !isPreviousDollar && !isLastDollar && i >= lastDot) {
break indexFound;
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is significant code duplication for the logic that determines when to replace '$' with '.' (or vice versa). This same pattern appears in at least 8 different methods across Signature.java, Util.java, NameLookup.java, and NamedMember.java. Consider extracting this logic into a shared utility method to improve maintainability. A method like shouldReplaceDollarWithDot(char[] array, int index, int lastDot, int lastDollar) would reduce duplication and make the logic easier to maintain and test.

Copilot uses AI. Check for mistakes.
Comment on lines 412 to 413
// return this.typeName;
// Internal class file name doesn't contain ".class" file extension
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple lines of commented-out code that should be removed before merging. Commented-out code makes the codebase harder to maintain and understand.

Suggested change
// return this.typeName;
// Internal class file name doesn't contain ".class" file extension

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

continue;
}
boolean isPrevDollar = (i > 0) ? (chars[i - 1] == '$') : false;
boolean isNextDollar = (i + 1 < chars.length) ? (chars[i + 1] == '$') : false;
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test is always true, because of this condition.
Test is always true, because of this condition.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct.
See https://github.com/clembo590/issues/tree/vscode-java/issues/2219
An example

public class Main {
	public static void main(String[] args) {
		String name = "UndertowWebServerFactoryCustomizer$AbstractOptions";
		char[] chars = name.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			boolean isPrevDollar = (i > 0) ? (chars[i - 1] == '$') : false;
			boolean isNextDollar = (i + 1 < chars.length) ? (chars[i + 1] == '$') : false;
			if (chars[i] == '$' && !isNextDollar && !isPrevDollar) {
				System.out.println("*** true" + " " + name + " chars[" + i + "]=" + chars[i] + " " + isPrevDollar + " "
						+ isNextDollar);
			} else {
				System.out.println("XXX false" + " " + name + " chars[" + i + "]=" + chars[i] + " " + isPrevDollar + " "
						+ isNextDollar);
			}
		}
	}
}

@iloveeclipse
Copy link
Member

@fbricon : I've rebased on latest & asked Copilot for review. Looks like there is a room for improvement.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@iloveeclipse
Copy link
Member

@snjeza : could you please squash two commits in one? Thanks.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@SentryMan
Copy link

perchance is there anything else needed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issues with classes starting with $

5 participants

Comments