diff --git a/blink/cmd/check-sources/main.go b/blink/cmd/check-sources/main.go index 2bdf4c1f6a..38edd37517 100644 --- a/blink/cmd/check-sources/main.go +++ b/blink/cmd/check-sources/main.go @@ -1,74 +1,237 @@ // Command check-sources verifies that every registered fixer links to a // reachable PHP-CS-Fixer source file on GitHub. It is run in CI so a renamed or -// removed upstream rule fails the build. GitHub rate-limits bursts of HEAD -// requests with 503/429, so each URL is retried with backoff before failing. +// removed upstream rule fails the build. +// +// Rather than one HEAD request per fixer (164 of them, which GitHub throttles +// with 503/429), it fetches the recursive file tree of each source repository +// in a single GitHub API call and checks every fixer path against that set. +// The last known-good tree is cached in sources_cache.json (committed and +// embedded) and used as a fallback when GitHub is unreachable. Run with +// -refresh to regenerate that committed cache. package main import ( + _ "embed" + "encoding/json" + "flag" "fmt" + "io" "net/http" "os" + "sort" + "strings" "time" + "blink/internal/fixer" "blink/internal/fixer/rules" ) +//go:embed sources_cache.json +var embeddedCache []byte + const maxAttempts = 4 -// checkURL returns the final status code (or an error) for url, retrying on a -// 5xx or 429 that GitHub returns when throttling a burst of requests. -func checkURL(client *http.Client, url string) (int, error) { - var lastStatus int +// sourceBases are the GitHub locations whose file trees back the fixer sources. +var sourceBases = []string{ + fixer.SourceBase, + fixer.SymplifySourceBase, + fixer.EcsSrcSourceBase, +} + +// cache maps each source base URL to the set of file paths that exist under it, +// relative to the base (e.g. "Alias/NoAliasFunctionsFixer.php"). +type cache map[string][]string + +// treeResponse is the subset of the GitHub git-trees API we read. +type treeResponse struct { + Tree []struct { + Path string `json:"path"` + Type string `json:"type"` + } `json:"tree"` + Truncated bool `json:"truncated"` +} + +// parseBase splits a source base URL into the GitHub owner, repo, branch, and +// the path prefix within the repo (e.g. "src/Fixer/"). +func parseBase(base string) (owner, repo, branch, prefix string, err error) { + rest, ok := strings.CutPrefix(base, "https://github.com/") + if !ok { + return "", "", "", "", fmt.Errorf("unexpected base URL %q", base) + } + parts := strings.SplitN(rest, "/", 5) + if len(parts) < 5 || parts[2] != "blob" { + return "", "", "", "", fmt.Errorf("cannot parse base URL %q", base) + } + return parts[0], parts[1], parts[3], parts[4], nil +} + +// fetchTree returns the file paths under base, relative to the base prefix, by +// reading the repository's recursive git tree in one request. +func fetchTree(client *http.Client, base string) ([]string, error) { + owner, repo, branch, prefix, err := parseBase(base) + if err != nil { + return nil, err + } + url := fmt.Sprintf("https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1", owner, repo, branch) + + var body []byte var lastErr error for attempt := 1; attempt <= maxAttempts; attempt++ { - req, err := http.NewRequest(http.MethodHead, url, nil) + req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { - return 0, err + return nil, err } req.Header.Set("User-Agent", "blink-check-sources") + req.Header.Set("Accept", "application/vnd.github+json") + if token := os.Getenv("GITHUB_TOKEN"); token != "" { + req.Header.Set("Authorization", "Bearer "+token) + } resp, err := client.Do(req) if err != nil { lastErr = err } else { + body, lastErr = io.ReadAll(resp.Body) _ = resp.Body.Close() - lastStatus, lastErr = resp.StatusCode, nil - if resp.StatusCode == http.StatusOK { - return resp.StatusCode, nil + if resp.StatusCode == http.StatusOK && lastErr == nil { + lastErr = nil + break } - // a 4xx other than 429 is a genuine missing/renamed source, not throttling - if resp.StatusCode != http.StatusTooManyRequests && resp.StatusCode < 500 { - return resp.StatusCode, nil + if lastErr == nil { + lastErr = fmt.Errorf("%s -> %d", url, resp.StatusCode) + } + if resp.StatusCode < 500 && resp.StatusCode != http.StatusTooManyRequests { + return nil, lastErr } } if attempt < maxAttempts { time.Sleep(time.Duration(attempt) * 2 * time.Second) } } - return lastStatus, lastErr + if lastErr != nil { + return nil, lastErr + } + + var tree treeResponse + if err := json.Unmarshal(body, &tree); err != nil { + return nil, err + } + if tree.Truncated { + return nil, fmt.Errorf("git tree for %s/%s truncated; cannot verify sources", owner, repo) + } + + var paths []string + for _, entry := range tree.Tree { + if entry.Type != "blob" { + continue + } + rel, ok := strings.CutPrefix(entry.Path, prefix) + if ok && strings.HasSuffix(rel, ".php") { + paths = append(paths, rel) + } + } + sort.Strings(paths) + return paths, nil +} + +// buildCache fetches the tree for every source base. +func buildCache(client *http.Client) (cache, error) { + result := cache{} + for _, base := range sourceBases { + paths, err := fetchTree(client, base) + if err != nil { + return nil, fmt.Errorf("fetch %s: %w", base, err) + } + result[base] = paths + } + return result, nil +} + +// refresh regenerates the committed cache file from live GitHub data. +func refresh(client *http.Client, path string) error { + built, err := buildCache(client) + if err != nil { + return err + } + data, err := json.MarshalIndent(built, "", " ") + if err != nil { + return err + } + data = append(data, '\n') + if err := os.WriteFile(path, data, 0o644); err != nil { + return err + } + fmt.Printf("Wrote %s\n", path) + return nil +} + +// sets turns a cache into fast lookup sets keyed by source base. +func sets(c cache) map[string]map[string]bool { + out := make(map[string]map[string]bool, len(c)) + for base, paths := range c { + set := make(map[string]bool, len(paths)) + for _, p := range paths { + set[p] = true + } + out[base] = set + } + return out } func main() { - client := &http.Client{Timeout: 20 * time.Second} - failed := false + refreshFlag := flag.Bool("refresh", false, "regenerate the committed sources_cache.json from live GitHub data") + cachePath := flag.String("cache", "cmd/check-sources/sources_cache.json", "path to the sources cache file") + flag.Parse() + client := &http.Client{Timeout: 30 * time.Second} + + if *refreshFlag { + if err := refresh(client, *cachePath); err != nil { + fmt.Fprintf(os.Stderr, "refresh failed: %v\n", err) + os.Exit(1) + } + return + } + + // Prefer live data so a renamed or removed upstream rule is caught, and fall + // back to the committed cache when GitHub is unreachable. + current, err := buildCache(client) + if err != nil { + fmt.Printf("live fetch failed (%v); using committed cache\n", err) + if err := json.Unmarshal(embeddedCache, ¤t); err != nil { + fmt.Fprintf(os.Stderr, "cannot read committed cache: %v\n", err) + os.Exit(1) + } + } + lookup := sets(current) + + failed := false for _, f := range rules.All() { url := f.SourceURL() - status, err := checkURL(client, url) + base, rel := splitSource(url) + set, ok := lookup[base] switch { - case err != nil: - fmt.Printf("FAIL %s: %v\n", f.Name(), err) + case !ok: + fmt.Printf("FAIL %s: no source tree for %s\n", f.Name(), base) failed = true - case status != http.StatusOK: - fmt.Printf("FAIL %s: %s -> %d\n", f.Name(), url, status) + case !set[rel]: + fmt.Printf("FAIL %s: %s missing from upstream\n", f.Name(), url) failed = true - default: - fmt.Printf("OK %s\n", url) } - time.Sleep(150 * time.Millisecond) // throttle so GitHub does not rate-limit the burst } if failed { os.Exit(1) } - fmt.Println("All fixer sources reachable.") + fmt.Printf("All %d fixer sources reachable.\n", len(rules.All())) +} + +// splitSource splits a fixer SourceURL into its known base and the path relative +// to that base. +func splitSource(url string) (base, rel string) { + for _, b := range sourceBases { + if after, ok := strings.CutPrefix(url, b); ok { + return b, after + } + } + return url, "" } diff --git a/blink/cmd/check-sources/sources_cache.json b/blink/cmd/check-sources/sources_cache.json new file mode 100644 index 0000000000..5c2475ea99 --- /dev/null +++ b/blink/cmd/check-sources/sources_cache.json @@ -0,0 +1,390 @@ +{ + "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/src/Fixer/": [ + "AbstractIncrementOperatorFixer.php", + "AbstractPhpUnitFixer.php", + "AbstractShortOperatorFixer.php", + "Alias/ArrayPushFixer.php", + "Alias/BacktickToShellExecFixer.php", + "Alias/EregToPregFixer.php", + "Alias/MbStrFunctionsFixer.php", + "Alias/ModernizeStrposFixer.php", + "Alias/NoAliasFunctionsFixer.php", + "Alias/NoAliasLanguageConstructCallFixer.php", + "Alias/NoMixedEchoPrintFixer.php", + "Alias/PowToExponentiationFixer.php", + "Alias/RandomApiMigrationFixer.php", + "Alias/SetTypeToCastFixer.php", + "ArrayNotation/ArraySyntaxFixer.php", + "ArrayNotation/NoMultilineWhitespaceAroundDoubleArrowFixer.php", + "ArrayNotation/NoTrailingCommaInSinglelineArrayFixer.php", + "ArrayNotation/NoWhitespaceBeforeCommaInArrayFixer.php", + "ArrayNotation/NoWhitespaceInEmptyArrayFixer.php", + "ArrayNotation/NormalizeIndexBraceFixer.php", + "ArrayNotation/ReturnToYieldFromFixer.php", + "ArrayNotation/TrimArraySpacesFixer.php", + "ArrayNotation/WhitespaceAfterCommaInArrayFixer.php", + "ArrayNotation/YieldFromArrayToYieldsFixer.php", + "AttributeNotation/AttributeBlockNoSpacesFixer.php", + "AttributeNotation/AttributeEmptyParenthesesFixer.php", + "AttributeNotation/GeneralAttributeRemoveFixer.php", + "AttributeNotation/OrderedAttributesFixer.php", + "Basic/BracesFixer.php", + "Basic/BracesPositionFixer.php", + "Basic/CurlyBracesPositionFixer.php", + "Basic/EncodingFixer.php", + "Basic/NoMultipleStatementsPerLineFixer.php", + "Basic/NoTrailingCommaInSinglelineFixer.php", + "Basic/NonPrintableCharacterFixer.php", + "Basic/NumericLiteralSeparatorFixer.php", + "Basic/OctalNotationFixer.php", + "Basic/PsrAutoloadingFixer.php", + "Basic/SingleLineEmptyBodyFixer.php", + "Casing/ClassReferenceNameCasingFixer.php", + "Casing/ConstantCaseFixer.php", + "Casing/IntegerLiteralCaseFixer.php", + "Casing/LowercaseKeywordsFixer.php", + "Casing/LowercaseStaticReferenceFixer.php", + "Casing/MagicConstantCasingFixer.php", + "Casing/MagicMethodCasingFixer.php", + "Casing/NativeFunctionCasingFixer.php", + "Casing/NativeFunctionTypeDeclarationCasingFixer.php", + "Casing/NativeTypeDeclarationCasingFixer.php", + "CastNotation/CastSpacesFixer.php", + "CastNotation/LowercaseCastFixer.php", + "CastNotation/ModernizeTypesCastingFixer.php", + "CastNotation/NoShortBoolCastFixer.php", + "CastNotation/NoUnsetCastFixer.php", + "CastNotation/ShortScalarCastFixer.php", + "ClassNotation/ClassAttributesSeparationFixer.php", + "ClassNotation/ClassDefinitionFixer.php", + "ClassNotation/FinalClassFixer.php", + "ClassNotation/FinalInternalClassFixer.php", + "ClassNotation/FinalPublicMethodForAbstractClassFixer.php", + "ClassNotation/ModernSerializationMethodsFixer.php", + "ClassNotation/ModifierKeywordsFixer.php", + "ClassNotation/NoBlankLinesAfterClassOpeningFixer.php", + "ClassNotation/NoNullPropertyInitializationFixer.php", + "ClassNotation/NoPhp4ConstructorFixer.php", + "ClassNotation/NoRedundantReadonlyPropertyFixer.php", + "ClassNotation/NoUnneededFinalMethodFixer.php", + "ClassNotation/OrderedClassElementsFixer.php", + "ClassNotation/OrderedInterfacesFixer.php", + "ClassNotation/OrderedTraitsFixer.php", + "ClassNotation/OrderedTypesFixer.php", + "ClassNotation/PhpdocReadonlyClassCommentToKeywordFixer.php", + "ClassNotation/ProtectedToPrivateFixer.php", + "ClassNotation/SelfAccessorFixer.php", + "ClassNotation/SelfStaticAccessorFixer.php", + "ClassNotation/SingleClassElementPerStatementFixer.php", + "ClassNotation/SingleTraitInsertPerStatementFixer.php", + "ClassNotation/StaticPrivateMethodFixer.php", + "ClassNotation/StringableForToStringFixer.php", + "ClassNotation/VisibilityRequiredFixer.php", + "ClassUsage/DateTimeImmutableFixer.php", + "Comment/CommentToPhpdocFixer.php", + "Comment/HeaderCommentFixer.php", + "Comment/MultilineCommentOpeningClosingFixer.php", + "Comment/NoEmptyCommentFixer.php", + "Comment/NoTrailingWhitespaceInCommentFixer.php", + "Comment/SingleLineCommentSpacingFixer.php", + "Comment/SingleLineCommentStyleFixer.php", + "ConfigurableFixerInterface.php", + "ConfigurableFixerTrait.php", + "ConstantNotation/NativeConstantInvocationFixer.php", + "ControlStructure/ControlStructureBracesFixer.php", + "ControlStructure/ControlStructureContinuationPositionFixer.php", + "ControlStructure/ElseifFixer.php", + "ControlStructure/EmptyLoopBodyFixer.php", + "ControlStructure/EmptyLoopConditionFixer.php", + "ControlStructure/IncludeFixer.php", + "ControlStructure/NoAlternativeSyntaxFixer.php", + "ControlStructure/NoBreakCommentFixer.php", + "ControlStructure/NoSuperfluousElseifFixer.php", + "ControlStructure/NoTrailingCommaInListCallFixer.php", + "ControlStructure/NoUnneededBracesFixer.php", + "ControlStructure/NoUnneededControlParenthesesFixer.php", + "ControlStructure/NoUnneededCurlyBracesFixer.php", + "ControlStructure/NoUselessElseFixer.php", + "ControlStructure/SimplifiedIfReturnFixer.php", + "ControlStructure/SwitchCaseSemicolonToColonFixer.php", + "ControlStructure/SwitchCaseSpaceFixer.php", + "ControlStructure/SwitchContinueToBreakFixer.php", + "ControlStructure/TrailingCommaInMultilineFixer.php", + "ControlStructure/YodaStyleFixer.php", + "DeprecatedFixerInterface.php", + "DocBlockAnnotationTrait.php", + "DoctrineAnnotation/DoctrineAnnotationArrayAssignmentFixer.php", + "DoctrineAnnotation/DoctrineAnnotationBracesFixer.php", + "DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php", + "DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php", + "ExperimentalFixerInterface.php", + "FixerInterface.php", + "FunctionNotation/CombineNestedDirnameFixer.php", + "FunctionNotation/DateTimeCreateFromFormatCallFixer.php", + "FunctionNotation/FopenFlagOrderFixer.php", + "FunctionNotation/FopenFlagsFixer.php", + "FunctionNotation/FunctionDeclarationFixer.php", + "FunctionNotation/FunctionTypehintSpaceFixer.php", + "FunctionNotation/ImplodeCallFixer.php", + "FunctionNotation/LambdaNotUsedImportFixer.php", + "FunctionNotation/MethodArgumentSpaceFixer.php", + "FunctionNotation/MultilinePromotedPropertiesFixer.php", + "FunctionNotation/NativeFunctionInvocationFixer.php", + "FunctionNotation/NoSpacesAfterFunctionNameFixer.php", + "FunctionNotation/NoTrailingCommaInSinglelineFunctionCallFixer.php", + "FunctionNotation/NoUnreachableDefaultArgumentValueFixer.php", + "FunctionNotation/NoUselessPrintfFixer.php", + "FunctionNotation/NoUselessSprintfFixer.php", + "FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php", + "FunctionNotation/PhpdocToParamTypeFixer.php", + "FunctionNotation/PhpdocToPropertyTypeFixer.php", + "FunctionNotation/PhpdocToReturnTypeFixer.php", + "FunctionNotation/RegularCallableCallFixer.php", + "FunctionNotation/ReturnTypeDeclarationFixer.php", + "FunctionNotation/SingleLineThrowFixer.php", + "FunctionNotation/StaticLambdaFixer.php", + "FunctionNotation/UseArrowFunctionsFixer.php", + "FunctionNotation/VoidReturnFixer.php", + "Import/FullyQualifiedStrictTypesFixer.php", + "Import/GlobalNamespaceImportFixer.php", + "Import/GroupImportFixer.php", + "Import/NoLeadingImportSlashFixer.php", + "Import/NoUnneededImportAliasFixer.php", + "Import/NoUnusedImportsFixer.php", + "Import/OrderedImportsFixer.php", + "Import/SingleImportPerStatementFixer.php", + "Import/SingleLineAfterImportsFixer.php", + "IndentationTrait.php", + "Internal/ConfigurableFixerTemplateFixer.php", + "InternalFixerInterface.php", + "LanguageConstruct/ClassKeywordFixer.php", + "LanguageConstruct/ClassKeywordRemoveFixer.php", + "LanguageConstruct/CombineConsecutiveIssetsFixer.php", + "LanguageConstruct/CombineConsecutiveUnsetsFixer.php", + "LanguageConstruct/DeclareEqualNormalizeFixer.php", + "LanguageConstruct/DeclareParenthesesFixer.php", + "LanguageConstruct/DirConstantFixer.php", + "LanguageConstruct/ErrorSuppressionFixer.php", + "LanguageConstruct/ExplicitIndirectVariableFixer.php", + "LanguageConstruct/FunctionToConstantFixer.php", + "LanguageConstruct/GetClassToClassKeywordFixer.php", + "LanguageConstruct/IsNullFixer.php", + "LanguageConstruct/NoUnsetOnPropertyFixer.php", + "LanguageConstruct/NullableTypeDeclarationFixer.php", + "LanguageConstruct/SingleSpaceAfterConstructFixer.php", + "LanguageConstruct/SingleSpaceAroundConstructFixer.php", + "ListNotation/ListSyntaxFixer.php", + "NamespaceNotation/BlankLineAfterNamespaceFixer.php", + "NamespaceNotation/BlankLinesBeforeNamespaceFixer.php", + "NamespaceNotation/CleanNamespaceFixer.php", + "NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php", + "NamespaceNotation/NoLeadingNamespaceWhitespaceFixer.php", + "NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php", + "Naming/NoHomoglyphNamesFixer.php", + "Operator/AssignNullCoalescingToCoalesceEqualFixer.php", + "Operator/BinaryOperatorSpacesFixer.php", + "Operator/ConcatSpaceFixer.php", + "Operator/IncrementStyleFixer.php", + "Operator/LogicalOperatorsFixer.php", + "Operator/LongToShorthandOperatorFixer.php", + "Operator/NewExpressionParenthesesFixer.php", + "Operator/NewWithBracesFixer.php", + "Operator/NewWithParenthesesFixer.php", + "Operator/NoSpaceAroundDoubleColonFixer.php", + "Operator/NoUselessConcatOperatorFixer.php", + "Operator/NoUselessNullsafeOperatorFixer.php", + "Operator/NotOperatorWithSpaceFixer.php", + "Operator/NotOperatorWithSuccessorSpaceFixer.php", + "Operator/ObjectOperatorWithoutWhitespaceFixer.php", + "Operator/OperatorLinebreakFixer.php", + "Operator/StandardizeIncrementFixer.php", + "Operator/StandardizeNotEqualsFixer.php", + "Operator/TernaryOperatorSpacesFixer.php", + "Operator/TernaryToElvisOperatorFixer.php", + "Operator/TernaryToNullCoalescingFixer.php", + "Operator/UnaryOperatorSpacesFixer.php", + "PhpTag/BlankLineAfterOpeningTagFixer.php", + "PhpTag/EchoTagSyntaxFixer.php", + "PhpTag/FullOpeningTagFixer.php", + "PhpTag/LinebreakAfterOpeningTagFixer.php", + "PhpTag/NoClosingTagFixer.php", + "PhpUnit/PhpUnitAssertNewNamesFixer.php", + "PhpUnit/PhpUnitAttributesFixer.php", + "PhpUnit/PhpUnitConstructFixer.php", + "PhpUnit/PhpUnitDataProviderMethodOrderFixer.php", + "PhpUnit/PhpUnitDataProviderNameFixer.php", + "PhpUnit/PhpUnitDataProviderReturnTypeFixer.php", + "PhpUnit/PhpUnitDataProviderStaticFixer.php", + "PhpUnit/PhpUnitDedicateAssertFixer.php", + "PhpUnit/PhpUnitDedicateAssertInternalTypeFixer.php", + "PhpUnit/PhpUnitExpectationFixer.php", + "PhpUnit/PhpUnitFqcnAnnotationFixer.php", + "PhpUnit/PhpUnitInternalClassFixer.php", + "PhpUnit/PhpUnitMethodCasingFixer.php", + "PhpUnit/PhpUnitMockFixer.php", + "PhpUnit/PhpUnitMockShortWillReturnFixer.php", + "PhpUnit/PhpUnitNamespacedFixer.php", + "PhpUnit/PhpUnitNoExpectationAnnotationFixer.php", + "PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php", + "PhpUnit/PhpUnitSizeClassFixer.php", + "PhpUnit/PhpUnitStrictFixer.php", + "PhpUnit/PhpUnitTargetVersion.php", + "PhpUnit/PhpUnitTestAnnotationFixer.php", + "PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php", + "PhpUnit/PhpUnitTestClassRequiresCoversFixer.php", + "Phpdoc/AlignMultilineCommentFixer.php", + "Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php", + "Phpdoc/GeneralPhpdocTagRenameFixer.php", + "Phpdoc/NoBlankLinesAfterPhpdocFixer.php", + "Phpdoc/NoEmptyPhpdocFixer.php", + "Phpdoc/NoSuperfluousPhpdocTagsFixer.php", + "Phpdoc/PhpdocAddMissingParamAnnotationFixer.php", + "Phpdoc/PhpdocAlignFixer.php", + "Phpdoc/PhpdocAnnotationWithoutDotFixer.php", + "Phpdoc/PhpdocArrayTypeFixer.php", + "Phpdoc/PhpdocIndentFixer.php", + "Phpdoc/PhpdocInlineTagNormalizerFixer.php", + "Phpdoc/PhpdocLineSpanFixer.php", + "Phpdoc/PhpdocListTypeFixer.php", + "Phpdoc/PhpdocNoAccessFixer.php", + "Phpdoc/PhpdocNoAliasTagFixer.php", + "Phpdoc/PhpdocNoDuplicateTypesFixer.php", + "Phpdoc/PhpdocNoEmptyReturnFixer.php", + "Phpdoc/PhpdocNoPackageFixer.php", + "Phpdoc/PhpdocNoUselessInheritdocFixer.php", + "Phpdoc/PhpdocOrderByValueFixer.php", + "Phpdoc/PhpdocOrderFixer.php", + "Phpdoc/PhpdocParamOrderFixer.php", + "Phpdoc/PhpdocReturnSelfReferenceFixer.php", + "Phpdoc/PhpdocScalarFixer.php", + "Phpdoc/PhpdocSeparationFixer.php", + "Phpdoc/PhpdocSingleLineVarSpacingFixer.php", + "Phpdoc/PhpdocSummaryFixer.php", + "Phpdoc/PhpdocTagCasingFixer.php", + "Phpdoc/PhpdocTagNoNamedArgumentsFixer.php", + "Phpdoc/PhpdocTagTypeFixer.php", + "Phpdoc/PhpdocToCommentFixer.php", + "Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixer.php", + "Phpdoc/PhpdocTrimFixer.php", + "Phpdoc/PhpdocTypesFixer.php", + "Phpdoc/PhpdocTypesNoDuplicatesFixer.php", + "Phpdoc/PhpdocTypesOrderFixer.php", + "Phpdoc/PhpdocVarAnnotationCorrectOrderFixer.php", + "Phpdoc/PhpdocVarWithoutNameFixer.php", + "ReturnNotation/NoUselessReturnFixer.php", + "ReturnNotation/ReturnAssignmentFixer.php", + "ReturnNotation/SimplifiedNullReturnFixer.php", + "Semicolon/MultilineWhitespaceBeforeSemicolonsFixer.php", + "Semicolon/NoEmptyStatementFixer.php", + "Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php", + "Semicolon/SemicolonAfterInstructionFixer.php", + "Semicolon/SpaceAfterSemicolonFixer.php", + "Strict/DeclareStrictTypesFixer.php", + "Strict/StrictComparisonFixer.php", + "Strict/StrictParamFixer.php", + "StringNotation/EscapeImplicitBackslashesFixer.php", + "StringNotation/ExplicitStringVariableFixer.php", + "StringNotation/HeredocClosingMarkerFixer.php", + "StringNotation/HeredocToNowdocFixer.php", + "StringNotation/MultilineStringToHeredocFixer.php", + "StringNotation/NoBinaryStringFixer.php", + "StringNotation/NoTrailingWhitespaceInStringFixer.php", + "StringNotation/SimpleToComplexStringVariableFixer.php", + "StringNotation/SingleQuoteFixer.php", + "StringNotation/StringImplicitBackslashesFixer.php", + "StringNotation/StringLengthToEmptyFixer.php", + "StringNotation/StringLineEndingFixer.php", + "Whitespace/ArrayIndentationFixer.php", + "Whitespace/BlankLineBeforeStatementFixer.php", + "Whitespace/BlankLineBetweenImportGroupsFixer.php", + "Whitespace/CompactNullableTypeDeclarationFixer.php", + "Whitespace/CompactNullableTypehintFixer.php", + "Whitespace/HeredocIndentationFixer.php", + "Whitespace/IndentationTypeFixer.php", + "Whitespace/LineEndingFixer.php", + "Whitespace/MethodChainingIndentationFixer.php", + "Whitespace/NoExtraBlankLinesFixer.php", + "Whitespace/NoSpacesAroundOffsetFixer.php", + "Whitespace/NoSpacesInsideParenthesisFixer.php", + "Whitespace/NoTrailingWhitespaceFixer.php", + "Whitespace/NoWhitespaceInBlankLineFixer.php", + "Whitespace/SingleBlankLineAtEofFixer.php", + "Whitespace/SpacesInsideParenthesesFixer.php", + "Whitespace/StatementIndentationFixer.php", + "Whitespace/TypeDeclarationSpacesFixer.php", + "Whitespace/TypesSpacesFixer.php", + "WhitespacesAwareFixerInterface.php" + ], + "https://github.com/ecsphp/ecs-src/blob/main/packages/coding-standard/src/Fixer/": [ + "AbstractSymplifyFixer.php", + "Annotation/RemoveEventSubscriberDescriptionFixer.php", + "Annotation/RemoveMethodNameDuplicateDescriptionFixer.php", + "Annotation/RemovePHPStormAnnotationFixer.php", + "Annotation/RemovePropertyVariableNameDescriptionFixer.php", + "ArrayNotation/ArrayListItemNewlineFixer.php", + "ArrayNotation/ArrayOpenerAndCloserNewlineFixer.php", + "ArrayNotation/StandaloneLineInMultilineArrayFixer.php", + "Commenting/AbstractDocBlockFixer.php", + "Commenting/AddMissingParamNameFixer.php", + "Commenting/AddMissingVarNameFixer.php", + "Commenting/DoubleAsteriskInlineVarFixer.php", + "Commenting/FixParamNameTypoFixer.php", + "Commenting/FixTagTypoFixer.php", + "Commenting/MergeDocBlockStartFixer.php", + "Commenting/ParamReturnAndVarTagMalformsFixer.php", + "Commenting/RemoveDeadParamFixer.php", + "Commenting/RemoveDeadVarThisFixer.php", + "Commenting/RemoveParamDescriptionDuplicateNameFixer.php", + "Commenting/RemoveParamNameReferenceFixer.php", + "Commenting/RemoveSuperfluousReturnNameFixer.php", + "Commenting/RemoveSuperfluousVarNameFixer.php", + "Commenting/RemoveUselessDefaultCommentFixer.php", + "Commenting/SingleLineInlineVarDocBlockFixer.php", + "Commenting/SwitchedTypeAndNameFixer.php", + "Commenting/TypeToVarTagFixer.php", + "LineLength/LineLengthFixer.php", + "Naming/ClassNameResolver.php", + "Naming/MethodNameResolver.php", + "Naming/PropertyNameResolver.php", + "Spacing/MethodChainingNewlineFixer.php", + "Spacing/NoBlankLineBetweenImportsFixer.php", + "Spacing/SpaceAfterCommaHereNowDocFixer.php", + "Spacing/StandaloneLineConstructorParamFixer.php", + "Spacing/StandaloneLinePlainConstructorParamFixer.php", + "Spacing/StandaloneLinePromotedPropertyFixer.php", + "Spacing/StandaloneLineRequiredParamFixer.php", + "Spacing/StandaloneLineSymfonyAttributeParamFixer.php", + "Strict/BlankLineAfterStrictTypesFixer.php" + ], + "https://github.com/symplify/coding-standard/blob/main/src/Fixer/": [ + "AbstractSymplifyFixer.php", + "Annotation/RemoveMethodNameDuplicateDescriptionFixer.php", + "Annotation/RemovePHPStormAnnotationFixer.php", + "Annotation/RemovePropertyVariableNameDescriptionFixer.php", + "ArrayNotation/ArrayListItemNewlineFixer.php", + "ArrayNotation/ArrayOpenerAndCloserNewlineFixer.php", + "ArrayNotation/StandaloneLineInMultilineArrayFixer.php", + "Commenting/AbstractDocBlockFixer.php", + "Commenting/AddMissingParamNameFixer.php", + "Commenting/AddMissingVarNameFixer.php", + "Commenting/DoubleAsteriskInlineVarFixer.php", + "Commenting/FixParamNameTypoFixer.php", + "Commenting/ParamReturnAndVarTagMalformsFixer.php", + "Commenting/RemoveDeadParamFixer.php", + "Commenting/RemoveParamNameReferenceFixer.php", + "Commenting/RemoveSuperfluousReturnNameFixer.php", + "Commenting/RemoveSuperfluousVarNameFixer.php", + "Commenting/RemoveUselessDefaultCommentFixer.php", + "Commenting/SingleLineInlineVarDocBlockFixer.php", + "Commenting/SwitchedTypeAndNameFixer.php", + "LineLength/LineLengthFixer.php", + "Naming/ClassNameResolver.php", + "Naming/MethodNameResolver.php", + "Naming/PropertyNameResolver.php", + "Spacing/MethodChainingNewlineFixer.php", + "Spacing/SpaceAfterCommaHereNowDocFixer.php", + "Spacing/StandaloneLineConstructorParamFixer.php", + "Spacing/StandaloneLinePromotedPropertyFixer.php", + "Strict/BlankLineAfterStrictTypesFixer.php" + ] +}