diff --git a/shortcuts/sheets/backward/lark_sheets_float_images.go b/shortcuts/sheets/backward/lark_sheets_float_images.go index 689b8ff6..b822a473 100644 --- a/shortcuts/sheets/backward/lark_sheets_float_images.go +++ b/shortcuts/sheets/backward/lark_sheets_float_images.go @@ -5,6 +5,7 @@ package backward import ( "context" + "errors" "fmt" "path/filepath" "strings" @@ -145,7 +146,8 @@ func validateSheetMediaUploadFile(runtime *common.RuntimeContext, filePath strin stat, err := runtime.FileIO().Stat(filePath) if err != nil { wrapped := common.WrapInputStatErrorTyped(err, "file not found") - if v, ok := wrapped.(*errs.ValidationError); ok { + var v *errs.ValidationError + if errors.As(wrapped, &v) { return "", nil, v.WithParam("--file") } return "", nil, wrapped diff --git a/shortcuts/sheets/flag_schema.go b/shortcuts/sheets/flag_schema.go index ccdbc7b0..b8b90de0 100644 --- a/shortcuts/sheets/flag_schema.go +++ b/shortcuts/sheets/flag_schema.go @@ -6,7 +6,6 @@ package sheets import ( _ "embed" "encoding/json" - "fmt" "sort" "sync" @@ -54,7 +53,7 @@ func loadFlagSchemas() (*flagSchemaIndex, error) { flagSchemasOnce.Do(func() { var idx flagSchemaIndex if err := json.Unmarshal(flagSchemasJSON, &idx); err != nil { - parseFlagErr = fmt.Errorf("flag-schemas.json: %w", err) + parseFlagErr = errs.NewInternalError(errs.SubtypeUnknown, "flag-schemas.json: %v", err).WithCause(err) return } if idx.Flags == nil { diff --git a/shortcuts/sheets/flag_schema_validate.go b/shortcuts/sheets/flag_schema_validate.go index 6e9af668..af433b57 100644 --- a/shortcuts/sheets/flag_schema_validate.go +++ b/shortcuts/sheets/flag_schema_validate.go @@ -243,7 +243,7 @@ func validateAgainstSchema(value interface{}, schema *schemaProperty, path strin if schema.Type != "" { if !matchesJSONType(value, schema.Type) { - return fmt.Errorf("%sexpected type %q, got %q", pathPrefix(path), schema.Type, jsType(value)) + return fmt.Errorf("%sexpected type %q, got %q", pathPrefix(path), schema.Type, jsType(value)) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } } @@ -251,20 +251,20 @@ func validateAgainstSchema(value interface{}, schema *schemaProperty, path strin // already reported above). Apply to both `number` and `integer` types. if num, ok := value.(float64); ok { if schema.Minimum != nil && num < *schema.Minimum { - return fmt.Errorf("%svalue %v is below minimum %v", pathPrefix(path), num, *schema.Minimum) + return fmt.Errorf("%svalue %v is below minimum %v", pathPrefix(path), num, *schema.Minimum) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } if schema.Maximum != nil && num > *schema.Maximum { - return fmt.Errorf("%svalue %v is above maximum %v", pathPrefix(path), num, *schema.Maximum) + return fmt.Errorf("%svalue %v is above maximum %v", pathPrefix(path), num, *schema.Maximum) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } } // Array length bounds — only checked when value is an array. if arr, ok := value.([]interface{}); ok { if schema.MinItems != nil && len(arr) < *schema.MinItems { - return fmt.Errorf("%sarray has %d items, minimum is %d", pathPrefix(path), len(arr), *schema.MinItems) + return fmt.Errorf("%sarray has %d items, minimum is %d", pathPrefix(path), len(arr), *schema.MinItems) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } if schema.MaxItems != nil && len(arr) > *schema.MaxItems { - return fmt.Errorf("%sarray has %d items, maximum is %d", pathPrefix(path), len(arr), *schema.MaxItems) + return fmt.Errorf("%sarray has %d items, maximum is %d", pathPrefix(path), len(arr), *schema.MaxItems) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } } @@ -282,7 +282,7 @@ func validateAgainstSchema(value interface{}, schema *schemaProperty, path strin if hint := suggestEnumMatch(value, schema.Enum); hint != "" { msg += fmt.Sprintf(` (did you mean %q?)`, hint) } - return fmt.Errorf("%s", msg) + return fmt.Errorf("%s", msg) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } } @@ -295,7 +295,7 @@ func validateAgainstSchema(value interface{}, schema *schemaProperty, path strin } } if !matched { - return fmt.Errorf("%svalue does not match any of oneOf alternatives", pathPrefix(path)) + return fmt.Errorf("%svalue does not match any of oneOf alternatives", pathPrefix(path)) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } } @@ -305,7 +305,7 @@ func validateAgainstSchema(value interface{}, schema *schemaProperty, path strin if obj, ok := value.(map[string]interface{}); ok { for _, key := range schema.Required { if _, present := obj[key]; !present { - return fmt.Errorf("required property %q is missing at %s", key, pathOrRoot(path)) + return fmt.Errorf("required property %q is missing at %s", key, pathOrRoot(path)) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } } if schema.Properties != nil { @@ -357,7 +357,7 @@ func validateAgainstSchema(value interface{}, schema *schemaProperty, path strin sort.Strings(extras) for _, key := range extras { if schema.AdditionalProperties.Strict { - return fmt.Errorf("%sunexpected property %q (not declared in schema)", pathPrefix(path), key) + return fmt.Errorf("%sunexpected property %q (not declared in schema)", pathPrefix(path), key) //nolint:forbidigo // intermediate error; validateFlagAgainstSchema wraps it into a typed flag validation error with a --print-schema hint } if schema.AdditionalProperties.Schema != nil { child := key diff --git a/shortcuts/sheets/flag_view.go b/shortcuts/sheets/flag_view.go index b31ed7b3..b3caf826 100644 --- a/shortcuts/sheets/flag_view.go +++ b/shortcuts/sheets/flag_view.go @@ -281,18 +281,18 @@ func (m mapFlagView) validateRawTypes() error { // parse time; reject here too to keep batch/standalone parity. f, isNum := val.(float64) if !isNum { - return fmt.Errorf("--%s must be a number, got %s", name, jsonTypeName(val)) + return fmt.Errorf("--%s must be a number, got %s", name, jsonTypeName(val)) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error } if math.Trunc(f) != f { - return fmt.Errorf("--%s must be an integer, got %s", name, strconv.FormatFloat(f, 'g', -1, 64)) + return fmt.Errorf("--%s must be an integer, got %s", name, strconv.FormatFloat(f, 'g', -1, 64)) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error } case "float64": if _, isNum := val.(float64); !isNum { - return fmt.Errorf("--%s must be a number, got %s", name, jsonTypeName(val)) + return fmt.Errorf("--%s must be a number, got %s", name, jsonTypeName(val)) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error } case "bool": if _, isBool := val.(bool); !isBool { - return fmt.Errorf("--%s must be a boolean, got %s", name, jsonTypeName(val)) + return fmt.Errorf("--%s must be a boolean, got %s", name, jsonTypeName(val)) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error } } } diff --git a/shortcuts/sheets/helpers.go b/shortcuts/sheets/helpers.go index 38a0bd9e..6d6a32d7 100644 --- a/shortcuts/sheets/helpers.go +++ b/shortcuts/sheets/helpers.go @@ -10,6 +10,7 @@ package sheets import ( "context" "encoding/json" + "errors" "fmt" neturl "net/url" "strings" @@ -44,7 +45,8 @@ func sheetsValidationCauseForFlag(name string, cause error) *errs.ValidationErro // classification and only adds the domain's flag param. func sheetsInputStatError(flag string, err error) error { wrapped := common.WrapInputStatErrorTyped(err) - if v, ok := wrapped.(*errs.ValidationError); ok { + var v *errs.ValidationError + if errors.As(wrapped, &v) { return v.WithParam(sheetsFlagParam(flag)) } return wrapped diff --git a/shortcuts/sheets/lark_sheet_sheet_structure.go b/shortcuts/sheets/lark_sheet_sheet_structure.go index d80355f8..e5c83e81 100644 --- a/shortcuts/sheets/lark_sheet_sheet_structure.go +++ b/shortcuts/sheets/lark_sheet_sheet_structure.go @@ -483,11 +483,11 @@ func dimGroupInput(runtime flagView, token, sheetID, sheetName, op string) (map[ func parseA1Range(s string) (dimension string, startIdx, endIdx int, err error) { s = strings.TrimSpace(s) if s == "" { - return "", 0, 0, fmt.Errorf("range is empty") + return "", 0, 0, fmt.Errorf("range is empty") //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } parts := strings.Split(s, ":") if len(parts) > 2 { - return "", 0, 0, fmt.Errorf("expected \"start:end\" or single element") + return "", 0, 0, fmt.Errorf("expected \"start:end\" or single element") //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } dim1, idx1, err := parseA1Position(parts[0]) if err != nil { @@ -501,10 +501,10 @@ func parseA1Range(s string) (dimension string, startIdx, endIdx int, err error) return "", 0, 0, err } if dim1 != dim2 { - return "", 0, 0, fmt.Errorf("cannot mix row (digits) and column (letters) in one range") + return "", 0, 0, fmt.Errorf("cannot mix row (digits) and column (letters) in one range") //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } if idx2 < idx1 { - return "", 0, 0, fmt.Errorf("end position is before start") + return "", 0, 0, fmt.Errorf("end position is before start") //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } return dim1, idx1, idx2, nil } @@ -515,7 +515,7 @@ func parseA1Range(s string) (dimension string, startIdx, endIdx int, err error) func parseA1Position(s string) (dimension string, idx int, err error) { s = strings.TrimSpace(s) if s == "" { - return "", 0, fmt.Errorf("position is empty") + return "", 0, fmt.Errorf("position is empty") //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } isDigits := true isLetters := true @@ -530,14 +530,14 @@ func parseA1Position(s string) (dimension string, idx int, err error) { if isDigits { n, _ := strconv.Atoi(s) if n <= 0 { - return "", 0, fmt.Errorf("row number must be >= 1 (got %q)", s) + return "", 0, fmt.Errorf("row number must be >= 1 (got %q)", s) //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } return "row", n - 1, nil } if isLetters { return "column", letterToColumnIndex(s), nil } - return "", 0, fmt.Errorf("expected pure digits (row number) or letters (column letter), got %q", s) + return "", 0, fmt.Errorf("expected pure digits (row number) or letters (column letter), got %q", s) //nolint:forbidigo // intermediate error; callers wrap it into a typed flag validation error } // columnIndexToLetter converts a 0-based column index to the spreadsheet diff --git a/shortcuts/sheets/lark_sheet_write_cells.go b/shortcuts/sheets/lark_sheet_write_cells.go index e6ff1e6d..be58e18b 100644 --- a/shortcuts/sheets/lark_sheet_write_cells.go +++ b/shortcuts/sheets/lark_sheet_write_cells.go @@ -631,23 +631,23 @@ func rangeDimensions(rangeStr string) (rows, cols int, err error) { } rangeStr = strings.TrimSpace(rangeStr) if rangeStr == "" { - return 0, 0, fmt.Errorf("empty range") + return 0, 0, fmt.Errorf("empty range") //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error } parts := strings.SplitN(rangeStr, ":", 2) if len(parts) == 1 { // single cell, e.g. "A1" if _, _, ok := splitCellRef(parts[0]); !ok { - return 0, 0, fmt.Errorf("invalid cell ref %q", parts[0]) + return 0, 0, fmt.Errorf("invalid cell ref %q", parts[0]) //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error } return 1, 1, nil } startCol, startRow, ok1 := splitCellRef(parts[0]) endCol, endRow, ok2 := splitCellRef(parts[1]) if !ok1 || !ok2 { - return 0, 0, fmt.Errorf("unsupported range form %q (need rectangular A1:B2)", rangeStr) + return 0, 0, fmt.Errorf("unsupported range form %q (need rectangular A1:B2)", rangeStr) //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error } if endRow < startRow || endCol < startCol { - return 0, 0, fmt.Errorf("end %q must be at or after start %q", parts[1], parts[0]) + return 0, 0, fmt.Errorf("end %q must be at or after start %q", parts[1], parts[0]) //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error } return endRow - startRow + 1, endCol - startCol + 1, nil }