Skip to content

Commit

Permalink
Further improved error message for member accesses.
Browse files Browse the repository at this point in the history
  • Loading branch information
erictraut committed Nov 2, 2023
1 parent 5b6d786 commit f45c068
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 8 deletions.
25 changes: 19 additions & 6 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,8 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}
}

let subDiag: DiagnosticAddendum | undefined;

if (!skipObjectTypeLookup) {
let effectiveFlags = flags;

Expand All @@ -2062,13 +2064,15 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
effectiveFlags |= MemberAccessFlags.DisallowClassVarWrites;
}

subDiag = diag ? new DiagnosticAddendum() : undefined;

// See if the member is present in the object itself.
memberInfo = getTypeOfClassMemberName(
errorNode,
objectType,
memberName,
usage,
diag,
subDiag,
effectiveFlags,
selfType
);
Expand All @@ -2086,15 +2090,22 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
effectiveFlags &= ~MemberAccessFlags.SkipInstanceMembers;
}

const metaclassDiag = diag ? new DiagnosticAddendum() : undefined;
memberInfo = getTypeOfClassMemberName(
errorNode,
ClassType.cloneAsInstance(metaclass),
memberName,
usage,
/* diag */ undefined,
metaclassDiag,
effectiveFlags,
objectTypeIsInstantiable ? objectType : ClassType.cloneAsInstantiable(objectType)
);

// If there was a descriptor error (as opposed to an error where the members
// was simply not found), use this diagnostic message.
if (memberInfo?.isDescriptorError) {
subDiag = metaclassDiag;
}
}

if (memberInfo && !memberInfo.isDescriptorError) {
Expand All @@ -2107,6 +2118,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
};
}

if (diag && subDiag) {
diag.addAddendum(subDiag);
}

return undefined;
}

Expand Down Expand Up @@ -5462,10 +5477,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
// No attribute of that name was found. If this is a member access
// through an object, see if there's an attribute access override
// method ("__getattr__", etc.).
if (
(flags & (MemberAccessFlags.SkipInstanceMembers | MemberAccessFlags.SkipAttributeAccessOverride)) ===
0
) {
if ((flags & MemberAccessFlags.SkipAttributeAccessOverride) === 0) {
const generalAttrType = applyAttributeAccessOverride(classType, errorNode, usage, memberName, selfType);
if (generalAttrType) {
return {
Expand All @@ -5480,6 +5492,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}
}

// Report that the member could not be accessed.
diag?.addMessage(Localizer.DiagnosticAddendum.memberUnknown().format({ name: memberName }));
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,8 @@
"bytesTypePromotions": "Set disableBytesTypePromotions to false to enable type promotion behavior for \"bytearray\" and \"memoryview\"",
"conditionalRequiresBool": "Method __bool__ for type \"{operandType}\" returns type \"{boolReturnType}\" rather than \"bool\"",
"dataClassFieldLocation": "Field declaration",
"descriptorAccessBindingFailed": "Failed to bind method \"{name}\" for class \"{className}\"",
"descriptorAccessCallFailed": "Failed to call method \"{name}\" for class \"{className}\"",
"descriptorAccessBindingFailed": "Failed to bind method \"{name}\" for descriptor class \"{className}\"",
"descriptorAccessCallFailed": "Failed to call method \"{name}\" for descriptor class \"{className}\"",
"dataClassFrozen": "\"{name}\" is frozen",
"finalMethod": "Final method",
"keyNotRequired": "\"{name}\" is not a required key in \"{type}\", so access may result in runtime exception",
Expand Down

0 comments on commit f45c068

Please sign in to comment.