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

Externalize Strings Wizard fails with "Entry is missing in property file" #947

Open
Phillipus opened this issue Nov 28, 2023 · 7 comments
Open
Assignees
Labels
bug Something isn't working

Comments

@Phillipus
Copy link

Phillipus commented Nov 28, 2023

  1. Import the attached project into your workspace - testproject.zip
  2. Open the Foo.java file
  3. Select from menu "Source -> Externalize Strings..."

The wizard cannot find the existing property strings with the error "Entry is missing in property file":

Image 001

Pressing "Next" on the wizard results in duplicate message declarations, so not possible to add new strings.

Eclipse 4.29
Java 17
All platforms

@Phillipus
Copy link
Author

This error occurs when the Messages.java file contains the BUNDLE_NAME declaration in this format:

private static final String BUNDLE_NAME = Messages.class.getPackageName() + ".messages";

If the BUNDLE_NAME is declared as a full string it is OK:

private static final String BUNDLE_NAME = "com.foo.bar.messages";

It means that adding new externalised strings to an already existing messages file is not possible.

@jjohnstn jjohnstn self-assigned this Nov 29, 2023
@jjohnstn jjohnstn added the bug Something isn't working label Nov 29, 2023
@Phillipus
Copy link
Author

Phillipus commented Nov 29, 2023

Seems that something strange is happening when initializing BUNDLE_NAME with String concatenation.

If we do the following, the wizard finds the messages correctly:

  1. Rename the messages.properties file to Messages.properties
  2. Change the initialization of BUNDLE_NAME in the Messages.java file to:
    private static final String BUNDLE_NAME = Messages.class.getName();

Now, if we edit that line to the following (concatenating an empty String), the wizard fails to find the messages:

private static final String BUNDLE_NAME = Messages.class.getName() + "";

In fact, the following doesn't work, either:

private static final String BUNDLE_NAME = "com.foo.bar.messages" + "";

or

private static final String BUNDLE_NAME = "com.foo.bar" + ".messages";

@Phillipus
Copy link
Author

Phillipus commented Nov 30, 2023

I'm by no means familiar with this code, but I've been tracing and debugging this issue and I think I've narrowed it down to NLSHintHelper method getResourceBundleName(CompilationUnit astRoot) and these lines in the anonymous ASTVIsitor:

private String getBundleName(Expression initializer) {
if (initializer instanceof StringLiteral)
return ((StringLiteral)initializer).getLiteralValue();
if (initializer instanceof MethodInvocation) {
MethodInvocation methInvocation= (MethodInvocation)initializer;
Expression exp= methInvocation.getExpression();
if ((exp != null) && (exp instanceof TypeLiteral)) {
SimpleType simple= (SimpleType)((TypeLiteral) exp).getType();
ITypeBinding typeBinding= simple.resolveBinding();
if (typeBinding != null)
return typeBinding.getQualifiedName();
}
}
return null;
}
});

When the messages bundle is declared using String concatenation the method parameter initializer can be of type InfixExpression and this is not handled.

@Phillipus
Copy link
Author

Phillipus commented Nov 30, 2023

One more finding. The getResourceBundleName method seems to return the Messages class name regardless of the actual method declaration.

So all of the following declarations result in the same bundle name:

private static final String BUNDLE_NAME = Messages.class.getName();

private static final String BUNDLE_NAME = Messages.class.getPackageName();

private static final String BUNDLE_NAME = Messages.class.getTypeName();

@Phillipus
Copy link
Author

Phillipus commented Dec 1, 2023

The following is a POC "fix" in NLSHintHelper line 282:

private String getBundleName(Expression initializer) {
	if (initializer instanceof StringLiteral)
		return ((StringLiteral)initializer).getLiteralValue();

	if (initializer instanceof MethodInvocation) {
		MethodInvocation methInvocation= (MethodInvocation)initializer;
		Expression exp= methInvocation.getExpression();
		if ((exp != null) && (exp instanceof TypeLiteral)) {
			SimpleType simple= (SimpleType)((TypeLiteral) exp).getType();
			ITypeBinding typeBinding= simple.resolveBinding();
			if (typeBinding != null) {
				if("getPackageName".equals(methInvocation.getName().getIdentifier()))
					return typeBinding.getPackage().getName(); 
				return typeBinding.getQualifiedName();
			}
		}
	}
	
	if (initializer instanceof InfixExpression ex)
		return getBundleName(ex.getLeftOperand()) + getBundleName(ex.getRightOperand());
	
	return null;
}

Original lines:

private String getBundleName(Expression initializer) {
if (initializer instanceof StringLiteral)
return ((StringLiteral)initializer).getLiteralValue();
if (initializer instanceof MethodInvocation) {
MethodInvocation methInvocation= (MethodInvocation)initializer;
Expression exp= methInvocation.getExpression();
if ((exp != null) && (exp instanceof TypeLiteral)) {
SimpleType simple= (SimpleType)((TypeLiteral) exp).getType();
ITypeBinding typeBinding= simple.resolveBinding();
if (typeBinding != null)
return typeBinding.getQualifiedName();
}
}
return null;
}
});

@kysmith-csg
Copy link

Maybe similar bug to #553? Sometimes when I get this bug, I guess maybe if the names don't conflict, it will actually blank out the warning ones so the wizard isn't really usable in that case.

@Phillipus
Copy link
Author

Maybe similar bug to #553?

That would be a side-effect of this one.

Effectively the use of class.getPackageName() makes the wizard unusable when you need to edit/add more strings. I've had to go back and change all instances to the fully qualified class string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants