boolean (@NotNull PyType expected, @NotNull PyTypedDictType actual, @NotNull PyExpression value) { final PyExpression valueWithoutKeyword = value instanceof PyKeywordArgument ? ((PyKeywordArgument)value).getValueExpression() : value; final PyTypedDictType.TypeCheckingResult result = PyTypedDictType.Companion.checkTypes(expected, actual, myTypeEvalContext, valueWithoutKeyword); if (result == null) return false; if (!result.getMatch()) { if (result.getValueTypeErrors().isEmpty() && result.getExtraKeys().isEmpty() && result.getMissingKeys().isEmpty()) { registerProblem(valueWithoutKeyword, PyPsiBundle.message("INSP.type.checker.expected.type.got.type.instead", PythonDocumentationProvider.getTypeName(expected, myTypeEvalContext), PythonDocumentationProvider.getTypeName(actual, myTypeEvalContext))); } if (!result.getValueTypeErrors().isEmpty()) { result.getValueTypeErrors().forEach(error -> { registerProblem(error.getActualExpression(), PyPsiBundle.message("INSP.type.checker.expected.type.got.type.instead", PythonDocumentationProvider.getTypeName( error.getExpectedType(), myTypeEvalContext), PythonDocumentationProvider.getTypeName(error.getActualType(), myTypeEvalContext))); }); if (!actual.isInferred()) { return true; } } if (!result.getExtraKeys().isEmpty()) { result.getExtraKeys().forEach(error -> { registerProblem(Objects.requireNonNullElse(error.getActualExpression(), valueWithoutKeyword), PyPsiBundle.message("INSP.type.checker.typed.dict.extra.key", error.getKey(), error.getExpectedTypedDictName())); }); } if (!result.getMissingKeys().isEmpty()) { result.getMissingKeys().forEach(error -> { final List<String> missingKeys = error.getMissingKeys(); registerProblem(error.getActualExpression() != null ? error.getActualExpression() : valueWithoutKeyword, PyPsiBundle.message("INSP.type.checker.typed.dict.missing.keys", error.getExpectedTypedDictName(), missingKeys.size(), StringUtil.join(missingKeys, s -> String.format("'%s'", s), ", "))); }); } } return true; }