fix: correct name length criterion for spelling fixes (#49575)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
AlCalzone
2022-07-07 18:08:37 +02:00
committed by GitHub
parent 59238dbf90
commit f6684be95e
32 changed files with 245 additions and 95 deletions

View File

@@ -1874,7 +1874,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
let result: Symbol | undefined;
let lastLocation: Node | undefined;
let lastSelfReferenceLocation: Node | undefined;
let propertyWithInvalidInitializer: Node | undefined;
let propertyWithInvalidInitializer: PropertyDeclaration | undefined;
let associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined;
let withinDeferredContext = false;
const errorLocation = location;
@@ -2008,6 +2008,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
if (ctor && ctor.locals) {
if (lookup(ctor.locals, name, meaning & SymbolFlags.Value)) {
// Remember the property node, it will be used later to report appropriate error
Debug.assertNode(location, isPropertyDeclaration);
propertyWithInvalidInitializer = location;
}
}
@@ -2204,11 +2205,31 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
}
}
}
// The invalid initializer error is needed in two situation:
// 1. When result is undefined, after checking for a missing "this."
// 2. When result is defined
function checkAndReportErrorForInvalidInitializer() {
if (propertyWithInvalidInitializer && !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields)) {
// We have a match, but the reference occurred within a property initializer and the identifier also binds
// to a local variable in the constructor where the code will be emitted. Note that this is actually allowed
// with ESNext+useDefineForClassFields because the scope semantics are different.
error(errorLocation,
errorLocation && propertyWithInvalidInitializer.type && textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos)
? Diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor
: Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor,
declarationNameToString(propertyWithInvalidInitializer.name), diagnosticName(nameArg!));
return true;
}
return false;
}
if (!result) {
if (nameNotFoundMessage) {
addLazyDiagnostic(() => {
if (!errorLocation ||
!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg!) && // TODO: GH#18217
!checkAndReportErrorForInvalidInitializer() &&
!checkAndReportErrorForExtendingInterface(errorLocation) &&
!checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
!checkAndReportErrorForExportingPrimitiveType(errorLocation, name) &&
@@ -2216,7 +2237,16 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
!checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) &&
!checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) {
let suggestion: Symbol | undefined;
if (getSpellingSuggestions && suggestionCount < maximumSuggestionCount) {
let suggestedLib: string | undefined;
// Report missing lib first
if (nameArg) {
suggestedLib = getSuggestedLibForNonExistentName(nameArg);
if (suggestedLib) {
error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg), suggestedLib);
}
}
// then spelling suggestions
if (!suggestedLib && getSpellingSuggestions && suggestionCount < maximumSuggestionCount) {
suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning);
const isGlobalScopeAugmentationDeclaration = suggestion?.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration);
if (isGlobalScopeAugmentationDeclaration) {
@@ -2238,16 +2268,9 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
}
}
}
if (!suggestion) {
if (nameArg) {
const lib = getSuggestedLibForNonExistentName(nameArg);
if (lib) {
error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg), lib);
}
else {
error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg));
}
}
// And then fall back to unspecified "not found"
if (!suggestion && !suggestedLib && nameArg) {
error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg));
}
suggestionCount++;
}
@@ -2255,14 +2278,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
}
return undefined;
}
if (propertyWithInvalidInitializer && !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields)) {
// We have a match, but the reference occurred within a property initializer and the identifier also binds
// to a local variable in the constructor where the code will be emitted. Note that this is actually allowed
// with ESNext+useDefineForClassFields because the scope semantics are different.
const propertyName = (propertyWithInvalidInitializer as PropertyDeclaration).name;
error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor,
declarationNameToString(propertyName), diagnosticName(nameArg!));
else if (checkAndReportErrorForInvalidInitializer()) {
return undefined;
}

View File

@@ -2105,7 +2105,7 @@ namespace ts {
* and 1 insertion/deletion at 3 characters)
*/
export function getSpellingSuggestion<T>(name: string, candidates: T[], getName: (candidate: T) => string | undefined): T | undefined {
const maximumLengthDifference = Math.min(2, Math.floor(name.length * 0.34));
const maximumLengthDifference = Math.max(2, Math.floor(name.length * 0.34));
let bestDistance = Math.floor(name.length * 0.4) + 1; // If the best result is worse than this, don't bother.
let bestCandidate: T | undefined;
for (const candidate of candidates) {

View File

@@ -3507,6 +3507,10 @@
"category": "Error",
"code": 2843
},
"Type of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor.": {
"category": "Error",
"code": 2844
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",