parameters: (
          ctxt: IDLCompatibilityContext, old_struct: syntax.Struct, new_struct: syntax.Struct,
          cmd_name: str, old_idl_file: syntax.IDLParsedSpec, new_idl_file: syntax.IDLParsedSpec,
          old_idl_file_path: str, new_idl_file_path: str, is_command_parameter: bool)
docstring: Check compatibility between old and new parameters or command type fields.
docstring_summary: Check compatibility between old and new parameters or command type fields.
docstring_tokens: Check compatibility between old and new parameters or command type fields .
function: def check_command_params_or_type_struct_fields(
          ctxt: IDLCompatibilityContext, old_struct: syntax.Struct, new_struct: syntax.Struct,
          cmd_name: str, old_idl_file: syntax.IDLParsedSpec, new_idl_file: syntax.IDLParsedSpec,
          old_idl_file_path: str, new_idl_file_path: str, is_command_parameter: bool):
      """Check compatibility between old and new parameters or command type fields."""
      # pylint: disable=too-many-arguments,too-many-branches
      # Check chained types.
      for old_chained_type in old_struct.chained_types or []:
          resolved_old_chained_type = get_chained_type_or_struct(old_chained_type, old_idl_file,
                                                                 old_idl_file_path)
          if resolved_old_chained_type is not None:
              for new_chained_type in new_struct.chained_types or []:
                  resolved_new_chained_type = get_chained_type_or_struct(
                      new_chained_type, new_idl_file, new_idl_file_path)
                  if (resolved_new_chained_type is not None
                          and resolved_old_chained_type.name == resolved_new_chained_type.name):
                      # Check that the old and new version of each chained type is also compatible.
                      old = FieldCompatibility(resolved_old_chained_type, old_idl_file,
                                               old_idl_file_path, unstable=False, optional=False)
                      new = FieldCompatibility(resolved_new_chained_type, new_idl_file,
                                               new_idl_file_path, unstable=False, optional=False)
                      check_param_or_command_type(
                          ctxt, FieldCompatibilityPair(old, new, cmd_name, old_struct.name),
                          is_command_parameter=False)
                      break
  
              else:
                  # old chained type was not found in new chained types.
                  ctxt.add_new_command_or_param_chained_type_not_superset_error(
                      cmd_name, old_chained_type.name, new_idl_file_path, old_struct.name,
                      is_command_parameter)
  
      old_struct_fields = get_all_struct_fields(old_struct, old_idl_file, old_idl_file_path)
      new_struct_fields = get_all_struct_fields(new_struct, new_idl_file, new_idl_file_path)
  
      # We need to special-case the stmtId parameter because it was removed. However, it's not a
      # breaking change to the API because it was added and removed behind a feature flag, so it was
      # never officially released.
      allow_list = ["endSessions-param-stmtId", "refreshSessions-param-stmtId"]
  
      for old_field in old_struct_fields or []:
          new_field_exists = False
          for new_field in new_struct_fields or []:
              if new_field.name == old_field.name:
                  new_field_exists = True
                  check_command_param_or_type_struct_field(
                      ctxt, old_field, new_field, cmd_name, old_idl_file, new_idl_file,
                      old_idl_file_path, new_idl_file_path, old_struct.name, is_command_parameter)
  
                  break
          allow_name: str = cmd_name + "-param-" + old_field.name
          if not new_field_exists and not old_field.unstable and allow_name not in allow_list:
              ctxt.add_new_param_or_command_type_field_missing_error(
                  cmd_name, old_field.name, old_idl_file_path, old_struct.name, is_command_parameter)
  
      # Check if a new field has been added to the parameters or type struct.
      # If so, it must be optional.
      for new_field in new_struct_fields or []:
          # Check that all fields in the new IDL have specified the 'unstable' field.
          if new_field.unstable is None:
              ctxt.add_new_param_or_command_type_field_requires_unstable_error(
                  cmd_name, new_field.name, new_idl_file_path, is_command_parameter)
  
          newly_added = True
          for old_field in old_struct_fields or []:
              if new_field.name == old_field.name:
                  newly_added = False
  
          if newly_added:
              new_field_type = get_field_type(new_field, new_idl_file, new_idl_file_path)
              new_field_optional = new_field.optional or (new_field_type
                                                          and new_field_type.name == 'optionalBool')
              if not new_field_optional and not new_field.unstable:
                  ctxt.add_new_param_or_command_type_field_added_required_error(
                      cmd_name, new_field.name, new_idl_file_path, new_struct.name,
                      is_command_parameter)
  
              # Check that a new field does not have an unallowed use of 'any' as the bson_serialization_type.
              any_allow_name: str = (cmd_name + "-param-" + new_field.name
                                     if is_command_parameter else cmd_name)
              # If we encounter a bson_serialization_type of None, we skip checking if 'any' is used.
              if isinstance(
                      new_field_type, syntax.Type
              ) and new_field_type.bson_serialization_type is not None and "any" in new_field_type.bson_serialization_type:
                  # If 'any' is not explicitly allowed as the bson_serialization_type.
                  any_allow = any_allow_name in ALLOW_ANY_TYPE_LIST or new_field_type.name == 'optionalBool'
                  if not any_allow:
                      ctxt.add_command_or_param_type_bson_any_not_allowed_error(
                          cmd_name, new_field_type.name, old_idl_file_path, new_field.name,
                          is_command_parameter)
function_tokens: def check_command_params_or_type_struct_fields ( ctxt : IDLCompatibilityContext , old_struct : syntax . Struct , new_struct : syntax . Struct , cmd_name : str , old_idl_file : syntax . IDLParsedSpec , new_idl_file : syntax . IDLParsedSpec , old_idl_file_path : str , new_idl_file_path : str , is_command_parameter : bool ) : # pylint: disable=too-many-arguments,too-many-branches # Check chained types. for old_chained_type in old_struct . chained_types or [ ] : resolved_old_chained_type = get_chained_type_or_struct ( old_chained_type , old_idl_file , old_idl_file_path ) if resolved_old_chained_type is not None : for new_chained_type in new_struct . chained_types or [ ] : resolved_new_chained_type = get_chained_type_or_struct ( new_chained_type , new_idl_file , new_idl_file_path ) if ( resolved_new_chained_type is not None and resolved_old_chained_type . name == resolved_new_chained_type . name ) : # Check that the old and new version of each chained type is also compatible. old = FieldCompatibility ( resolved_old_chained_type , old_idl_file , old_idl_file_path , unstable = False , optional = False ) new = FieldCompatibility ( resolved_new_chained_type , new_idl_file , new_idl_file_path , unstable = False , optional = False ) check_param_or_command_type ( ctxt , FieldCompatibilityPair ( old , new , cmd_name , old_struct . name ) , is_command_parameter = False ) break else : # old chained type was not found in new chained types. ctxt . add_new_command_or_param_chained_type_not_superset_error ( cmd_name , old_chained_type . name , new_idl_file_path , old_struct . name , is_command_parameter ) old_struct_fields = get_all_struct_fields ( old_struct , old_idl_file , old_idl_file_path ) new_struct_fields = get_all_struct_fields ( new_struct , new_idl_file , new_idl_file_path ) # We need to special-case the stmtId parameter because it was removed. However, it's not a # breaking change to the API because it was added and removed behind a feature flag, so it was # never officially released. allow_list = [ "endSessions-param-stmtId" , "refreshSessions-param-stmtId" ] for old_field in old_struct_fields or [ ] : new_field_exists = False for new_field in new_struct_fields or [ ] : if new_field . name == old_field . name : new_field_exists = True check_command_param_or_type_struct_field ( ctxt , old_field , new_field , cmd_name , old_idl_file , new_idl_file , old_idl_file_path , new_idl_file_path , old_struct . name , is_command_parameter ) break allow_name : str = cmd_name + "-param-" + old_field . name if not new_field_exists and not old_field . unstable and allow_name not in allow_list : ctxt . add_new_param_or_command_type_field_missing_error ( cmd_name , old_field . name , old_idl_file_path , old_struct . name , is_command_parameter ) # Check if a new field has been added to the parameters or type struct. # If so, it must be optional. for new_field in new_struct_fields or [ ] : # Check that all fields in the new IDL have specified the 'unstable' field. if new_field . unstable is None : ctxt . add_new_param_or_command_type_field_requires_unstable_error ( cmd_name , new_field . name , new_idl_file_path , is_command_parameter ) newly_added = True for old_field in old_struct_fields or [ ] : if new_field . name == old_field . name : newly_added = False if newly_added : new_field_type = get_field_type ( new_field , new_idl_file , new_idl_file_path ) new_field_optional = new_field . optional or ( new_field_type and new_field_type . name == 'optionalBool' ) if not new_field_optional and not new_field . unstable : ctxt . add_new_param_or_command_type_field_added_required_error ( cmd_name , new_field . name , new_idl_file_path , new_struct . name , is_command_parameter ) # Check that a new field does not have an unallowed use of 'any' as the bson_serialization_type. any_allow_name : str = ( cmd_name + "-param-" + new_field . name if is_command_parameter else cmd_name ) # If we encounter a bson_serialization_type of None, we skip checking if 'any' is used. if isinstance ( new_field_type , syntax . Type ) and new_field_type . bson_serialization_type is not None and "any" in new_field_type . bson_serialization_type : # If 'any' is not explicitly allowed as the bson_serialization_type. any_allow = any_allow_name in ALLOW_ANY_TYPE_LIST or new_field_type . name == 'optionalBool' if not any_allow : ctxt . add_command_or_param_type_bson_any_not_allowed_error ( cmd_name , new_field_type . name , old_idl_file_path , new_field . name , is_command_parameter )