Bug 213692 - [compiler] Wrong unnecessary NON-NLS diagnostic after syntax recovery
Summary: [compiler] Wrong unnecessary NON-NLS diagnostic after syntax recovery
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.4   Edit
Hardware: PC Windows XP
: P2 normal (vote)
Target Milestone: 3.4 M5   Edit
Assignee: David Audel CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-12-21 07:27 EST by Philipe Mulet CLA
Modified: 2008-02-05 05:27 EST (History)
1 user (show)

See Also:


Attachments
Screenshot of offending warnings (105.18 KB, image/jpeg)
2007-12-21 07:30 EST, Philipe Mulet CLA
no flags Details
Proposed fix (19.13 KB, patch)
2008-01-10 09:18 EST, David Audel CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Philipe Mulet CLA 2007-12-21 07:27:53 EST
Build 3.4M4

The following code should not report unnecessary NON-NLS tag, but it does
(was editing PackageBinding.java in #toString() method)


-------------------------------

/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
import org.eclipse.jdt.internal.compiler.util.HashtableOfType;

public class PackageBinding extends Binding implements TypeConstants {
	public long tagBits = 0; // See values in the interface TagBits below

	public char[][] compoundName;
	PackageBinding parent;
	public LookupEnvironment environment;
	HashtableOfType knownTypes;
	HashtableOfPackage knownPackages;
protected PackageBinding() {
	// for creating problem package
}
public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) {
	this(new char[][] {topLevelPackageName}, null, environment);
}
/* Create the default package.
*/
public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) {
	this.compoundName = compoundName;
	this.parent = parent;
	this.environment = environment;
	this.knownTypes = null; // initialized if used... class counts can be very large 300-600
	this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
}

public PackageBinding(LookupEnvironment environment) {
	this(CharOperation.NO_CHAR_CHAR, null, environment);
}
private void addNotFoundPackage(char[] simpleName) {
	knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage);
}
private void addNotFoundType(char[] simpleName) {
	if (knownTypes == null)
		knownTypes = new HashtableOfType(25);
	knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType);
}
void addPackage(PackageBinding element) {
	if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit();
	knownPackages.put(element.compoundName[element.compoundName.length - 1], element);
}
void addType(ReferenceBinding element) {
	if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit();
	if (knownTypes == null)
		knownTypes = new HashtableOfType(25);
	knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
}

void clearMissingTagBit() {
	PackageBinding current = this;
	do {
		current.tagBits &= ~TagBits.HasMissingType;
	} while ((current = current.parent) != null);
}
/*
 * slash separated name
 * org.eclipse.jdt.core --> org/eclipse/jdt/core
 */
public char[] computeUniqueKey(boolean isLeaf) {
	return CharOperation.concatWith(compoundName, '/');
}
private PackageBinding findPackage(char[] name) {
	if (!environment.isPackage(this.compoundName, name))
		return null;

	char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name);
	PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, environment);
	addPackage(subPackageBinding);
	return subPackageBinding;
}
/* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
* Answer null if it could not be resolved.
*
* NOTE: This should only be used when we know there is NOT a type with the same name.
*/
PackageBinding getPackage(char[] name) {
	PackageBinding binding = getPackage0(name);
	if (binding != null) {
		if (binding == LookupEnvironment.TheNotFoundPackage)
			return null;
		else
			return binding;
	}
	if ((binding = findPackage(name)) != null)
		return binding;

	// not found so remember a problem package binding in the cache for future lookups
	addNotFoundPackage(name);
	return null;
}
/* Answer the subpackage named name if it exists in the cache.
* Answer theNotFoundPackage if it could not be resolved the first time
* it was looked up, otherwise answer null.
*
* NOTE: Senders must convert theNotFoundPackage into a real problem
* package if its to returned.
*/

PackageBinding getPackage0(char[] name) {
	return knownPackages.get(name);
}
/* Answer the type named name; ask the oracle for the type if its not in the cache.
* Answer a NotVisible problem type if the type is not visible from the invocationPackage.
* Answer null if it could not be resolved.
*
* NOTE: This should only be used by source types/scopes which know there is NOT a
* package with the same name.
*/

ReferenceBinding getType(char[] name) {
	ReferenceBinding typeBinding = getType0(name);
	if (typeBinding == null) {
		if ((typeBinding = environment.askForType(this, name)) == null) {
			// not found so remember a problem type binding in the cache for future lookups
			addNotFoundType(name);
			return null;
		}
	}

	if (typeBinding == LookupEnvironment.TheNotFoundType)
		return null;

	typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
	if (typeBinding.isNestedType())
		return new ProblemReferenceBinding(new char[][]{ name }, typeBinding, ProblemReasons.InternalNameProvided);
	return typeBinding;
}
/* Answer the type named name if it exists in the cache.
* Answer theNotFoundType if it could not be resolved the first time
* it was looked up, otherwise answer null.
*
* NOTE: Senders must convert theNotFoundType into a real problem
* reference type if its to returned.
*/

ReferenceBinding getType0(char[] name) {
	if (knownTypes == null)
		return null;
	return knownTypes.get(name);
}
/* Answer the package or type named name; ask the oracle if it is not in the cache.
* Answer null if it could not be resolved.
*
* When collisions exist between a type name & a package name, answer the type.
* Treat the package as if it does not exist... a problem was already reported when the type was defined.
*
* NOTE: no visibility checks are performed.
* THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
*/

public Binding getTypeOrPackage(char[] name) {
	ReferenceBinding typeBinding = getType0(name);
	if (typeBinding != null && typeBinding != LookupEnvironment.TheNotFoundType) {
		typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
		if (typeBinding.isNestedType())
			return new ProblemReferenceBinding(new char[][]{name}, typeBinding, ProblemReasons.InternalNameProvided);
		return typeBinding;
	}

	PackageBinding packageBinding = getPackage0(name);
	if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage)
		return packageBinding;

	if (typeBinding == null) { // have not looked for it before
		if ((typeBinding = environment.askForType(this, name)) != null) {
			if (typeBinding.isNestedType())
				return new ProblemReferenceBinding(new char[][]{name}, typeBinding, ProblemReasons.InternalNameProvided);
			return typeBinding;
		}

		// Since name could not be found, add a problem binding
		// to the collections so it will be reported as an error next time.
		addNotFoundType(name);
	}

	if (packageBinding == null) { // have not looked for it before
		if ((packageBinding = findPackage(name)) != null)
			return packageBinding;
		addNotFoundPackage(name);
	}

	return null;
}

/* API
* Answer the receiver's binding type from Binding.BindingID.
*/
public final int kind() {
	return Binding.PACKAGE;
}

public int problemId() {
	if ((this.tagBits & TagBits.HasMissingType) != 0)
		return ProblemReasons.NotFound;
	return ProblemReasons.NoError;
}

public char[] readableName() /*java.lang*/ {
	return CharOperation.concatWith(compoundName, '.');
}
public String toString() {
	String str;
	if (compoundName == CharOperation.NO_CHAR_CHAR) {
		str = "The Default Package"; //$NON-NLS-1$
	} else {
		str "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
	}
	if ((this.tagBits & TagBits.HasMissingType) != 0) {
		str += "[MISSING]"; //$NON-NLS-1$
	}
}
}
Comment 1 Philipe Mulet CLA 2007-12-21 07:30:16 EST
Created attachment 85710 [details]
Screenshot of offending warnings

Note that no marker got issued when building... reconcile only issue ?
Comment 2 Philipe Mulet CLA 2007-12-21 07:53:17 EST
Simpler testcase (extracted from another instance of a similar issue, could be a slightly different scenario thus).

public class X {
	public String toString() {
		StringBuffer output = new StringBuffer(10);
		output.append(this != null) ? null : "<no type>"); //$NON-NLS-1$
		output.append(" "); //$NON-NLS-1$
		return output.toString();
	}	
}

It seems that ternary expressions are causing grief to the recovery of NLS diagnostics.
Comment 3 David Audel CLA 2008-01-10 09:18:39 EST
Created attachment 86555 [details]
Proposed fix
Comment 4 David Audel CLA 2008-01-10 09:24:59 EST
Released for 3.4M5.

Tests added
  ExternalizeStringLiteralsTest#tesst018() -> test023()

NLSTag and StringLiteral wasn't recorded after a syntax error.
Comment 5 Frederic Fusier CLA 2008-02-05 05:27:56 EST
Verified for 3.4M5 using I20080204-0010 build.