From 6a69b0b6845dd5b0b3984a0fcc9a26d8f09ab051 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 9 Oct 2026 10:48:35 +0200 Subject: [PATCH 1/2] Build blink fixer registry once and precompile phpdoc tag regexes rules.All() rebuilt and re-sorted the full fixer list on every call, and ByName scanned it linearly - so config resolution, which calls ByName per rule, was quadratic. Build the sorted list and a name index once via sync.Once; All() returns a clone so callers may still append or reorder. PhpdocTagCasing and PhpdocInlineTagNormalizer recompiled their regexes on every Fix (once per file). Compile them in WithConfig instead. --- blink/internal/fixer/rules/gen_phpdoc_tags.go | 61 +++++++++++-------- blink/internal/fixer/rules/registry.go | 43 +++++++++---- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/blink/internal/fixer/rules/gen_phpdoc_tags.go b/blink/internal/fixer/rules/gen_phpdoc_tags.go index 90b3e5cbf2..e610aa9726 100644 --- a/blink/internal/fixer/rules/gen_phpdoc_tags.go +++ b/blink/internal/fixer/rules/gen_phpdoc_tags.go @@ -13,13 +13,32 @@ import ( // "@inheritdocs" untouched, mirroring the default ['inheritDoc'] tag set. var inheritDocRe = regexp.MustCompile(`(?i)@inheritdoc\b`) +type tagReplacement struct { + re *regexp.Regexp + to string +} + +// defaultTagReps is the ['inheritDoc'] replacement used when no tags are configured. +var defaultTagReps = []tagReplacement{{inheritDocRe, "@inheritDoc"}} + +func buildTagReps(tags []string) []tagReplacement { + reps := make([]tagReplacement, 0, len(tags)) + for _, tag := range tags { + reps = append(reps, tagReplacement{ + regexp.MustCompile(`(?i)@` + regexp.QuoteMeta(tag) + `\b`), + "@" + tag, + }) + } + return reps +} + // PHP-CS-Fixer: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/src/Fixer/Phpdoc/PhpdocTagCasingFixer.php // // PhpdocTagCasing fixes the casing of the configured tags (default ["inheritDoc"]), // in both annotation and inline positions. Each tag is matched case-insensitively // and rewritten to the configured spelling. type PhpdocTagCasing struct { - tags []string + reps []tagReplacement // nil means the default ['inheritDoc'] set } func (PhpdocTagCasing) Name() string { @@ -32,26 +51,15 @@ func (PhpdocTagCasing) SourceURL() string { func (f PhpdocTagCasing) WithConfig(config map[string]any) fixer.Fixer { if list, ok := phpdocTagsStringList(config["tags"]); ok { - f.tags = list + f.reps = buildTagReps(list) } return f } func (f PhpdocTagCasing) Fix(s *tokens.Stream) bool { - type replacement struct { - re *regexp.Regexp - to string - } - var reps []replacement - if f.tags == nil { - reps = []replacement{{inheritDocRe, "@inheritDoc"}} - } else { - for _, tag := range f.tags { - reps = append(reps, replacement{ - regexp.MustCompile(`(?i)@` + regexp.QuoteMeta(tag) + `\b`), - "@" + tag, - }) - } + reps := f.reps + if reps == nil { + reps = defaultTagReps } return applyToDocblocks(s, func(d *docblock) bool { changed := false @@ -99,7 +107,8 @@ var inlineTagRe = regexp.MustCompile(`(?i)(?:@\{+|\{+[ \t]*@)[ \t]*(example|id|i // job). Option `tags` selects which inline tags to normalize; a nil list keeps // blink's default set. type PhpdocInlineTagNormalizer struct { - tags []string + re *regexp.Regexp // nil means the default inlineTagRe set + disabled bool // an explicit empty tag list disables the fixer } func (PhpdocInlineTagNormalizer) Name() string { @@ -112,18 +121,22 @@ func (PhpdocInlineTagNormalizer) SourceURL() string { func (f PhpdocInlineTagNormalizer) WithConfig(config map[string]any) fixer.Fixer { if list, ok := phpdocTagsStringList(config["tags"]); ok { - f.tags = list + if len(list) == 0 { + f.disabled = true + } else { + f.re = phpdocInlineTagRe(list) + } } return f } func (f PhpdocInlineTagNormalizer) Fix(s *tokens.Stream) bool { - re := inlineTagRe - if f.tags != nil { - if len(f.tags) == 0 { - return false - } - re = phpdocInlineTagRe(f.tags) + if f.disabled { + return false + } + re := f.re + if re == nil { + re = inlineTagRe } return applyToDocblocks(s, func(d *docblock) bool { changed := false diff --git a/blink/internal/fixer/rules/registry.go b/blink/internal/fixer/rules/registry.go index c3c8598fe5..a4fa7361b3 100644 --- a/blink/internal/fixer/rules/registry.go +++ b/blink/internal/fixer/rules/registry.go @@ -1,8 +1,10 @@ package rules import ( + "slices" "sort" "strings" + "sync" "blink/internal/fixer" ) @@ -245,7 +247,14 @@ func StructuralFixers() []fixer.Fixer { // All returns every built-in fixer in execution order. FullOpeningTag runs first // (normalize the tag) and NoClosingTag last (trailing tag/EOF cleanup). -func All() []fixer.Fixer { +var ( + registryOnce sync.Once + sortedFixers []fixer.Fixer // canonical execution order + fixerByName map[string]fixer.Fixer // Name -> fixer + canonicalPos map[string]int // Name -> index in sortedFixers +) + +func buildRegistry() { all := []fixer.Fixer{FullOpeningTag{}} all = append(all, CommonFixers()...) all = append(all, PhpdocFixers()...) @@ -274,7 +283,21 @@ func All() []fixer.Fixer { } return fixerSortName(all[a]) < fixerSortName(all[b]) }) - return all + + sortedFixers = all + fixerByName = make(map[string]fixer.Fixer, len(all)) + canonicalPos = make(map[string]int, len(all)) + for i, f := range all { + fixerByName[f.Name()] = f + canonicalPos[f.Name()] = i + } +} + +// All returns every fixer in PHP-CS-Fixer execution order. The registry is built +// once; the returned slice is a fresh copy the caller may append to or reorder. +func All() []fixer.Fixer { + registryOnce.Do(buildRegistry) + return slices.Clone(sortedFixers) } // fixerSortName returns the name PHP-CS-Fixer sorts a fixer by: a core fixer's @@ -295,13 +318,10 @@ func fixerSortName(f fixer.Fixer) string { // applies rules in the same order as the standalone path. Fixers unknown to // All() are placed last. func CanonicalOrder(fixers []fixer.Fixer) { - idx := map[string]int{} - for i, f := range All() { - idx[f.Name()] = i - } + registryOnce.Do(buildRegistry) const last = 1 << 30 pos := func(f fixer.Fixer) int { - if i, ok := idx[f.Name()]; ok { + if i, ok := canonicalPos[f.Name()]; ok { return i } return last @@ -329,13 +349,10 @@ var deprecatedAliases = map[string]string{ // ByName returns the fixer whose Name matches, if any. func ByName(name string) (fixer.Fixer, bool) { + registryOnce.Do(buildRegistry) if canonical, ok := deprecatedAliases[name]; ok { name = canonical } - for _, f := range All() { - if f.Name() == name { - return f, true - } - } - return nil, false + f, ok := fixerByName[name] + return f, ok } From ca1e29fbb3a3d28249dd20dab766b13cfa0b0770 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 9 Oct 2026 10:48:35 +0200 Subject: [PATCH 2/2] Run blink rule tests in parallel The rule fixers are pure stateless value types over independent token streams, so their tests have no shared state. Mark each with t.Parallel() to cut test wall-time. --- .../rules/add_missing_param_name_test.go | 2 ++ .../fixer/rules/array_indentation_test.go | 1 + .../rules/array_list_item_newline_test.go | 1 + .../fixer/rules/array_notation_config_test.go | 1 + .../array_opener_and_closer_newline_test.go | 1 + blink/internal/fixer/rules/batch10_test.go | 9 ++++++ blink/internal/fixer/rules/batchA_test.go | 5 +++ blink/internal/fixer/rules/batchD_test.go | 1 + .../binary_operator_spaces_config_test.go | 1 + .../fixer/rules/blank_lines_config_test.go | 1 + .../rules/braces_position_config_test.go | 1 + .../fixer/rules/braces_position_test.go | 6 ++++ .../fixer/rules/casing_config_test.go | 1 + .../fixer/rules/cast_spaces_config_test.go | 1 + .../rules/class_definition_config_test.go | 2 ++ .../fixer/rules/class_elements_config_test.go | 1 + .../fixer/rules/class_members_test.go | 5 +++ .../fixer/rules/class_notation_test.go | 9 ++++++ blink/internal/fixer/rules/comments2_test.go | 1 + .../internal/fixer/rules/common_batch_test.go | 8 +++++ .../fixer/rules/concat_space_config_test.go | 1 + .../fixer/rules/constructs_config_test.go | 1 + .../rules/control_structure_braces_test.go | 1 + ...trol_structure_continuation_config_test.go | 1 + .../rules/control_structure_tier1_test.go | 2 ++ .../fixer/rules/declare_config_test.go | 1 + ...ctrine_annotation_array_assignment_test.go | 1 + .../doctrine_annotation_indentation_test.go | 1 + .../fixer/rules/doctrine_annotation_test.go | 2 ++ .../rules/explicit_string_variable_test.go | 1 + .../fully_qualified_strict_types_test.go | 1 + .../rules/function_to_constant_config_test.go | 1 + .../internal/fixer/rules/gen2_casing_test.go | 2 ++ .../fixer/rules/gen2_comment_config_test.go | 1 + .../internal/fixer/rules/gen2_comment_test.go | 2 ++ blink/internal/fixer/rules/gen2_ops_test.go | 3 ++ .../fixer/rules/gen2_phpdoc_config_test.go | 1 + .../internal/fixer/rules/gen2_phpdoc_test.go | 3 ++ .../fixer/rules/gen2_types_config_test.go | 1 + blink/internal/fixer/rules/gen2_types_test.go | 2 ++ .../fixer/rules/gen3_class_sep_config_test.go | 1 + .../fixer/rules/gen3_class_sep_test.go | 11 +++++++ .../fixer/rules/gen3_func_config_test.go | 3 ++ blink/internal/fixer/rules/gen3_func_test.go | 2 ++ .../fixer/rules/gen3_types_config_test.go | 1 + blink/internal/fixer/rules/gen3_types_test.go | 3 ++ blink/internal/fixer/rules/gen4_a_test.go | 3 ++ blink/internal/fixer/rules/gen4_b_test.go | 2 ++ .../fixer/rules/gen4_phpdoc_config_test.go | 1 + .../internal/fixer/rules/gen4_phpdoc_test.go | 3 ++ blink/internal/fixer/rules/gen5_lang_test.go | 4 +++ .../rules/gen5_phpdoc_misc_config_test.go | 1 + .../fixer/rules/gen5_phpdoc_misc_test.go | 2 ++ .../fixer/rules/gen5_phpdoc_order_test.go | 3 ++ .../internal/fixer/rules/gen6_phpdoc_test.go | 5 +++ blink/internal/fixer/rules/gen_arrays_test.go | 5 +++ .../internal/fixer/rules/gen_control_test.go | 2 ++ .../internal/fixer/rules/gen_imports_test.go | 3 ++ .../internal/fixer/rules/gen_ops_cast_test.go | 3 ++ .../internal/fixer/rules/gen_ops_inc_test.go | 5 +++ .../rules/gen_phpdoc_tags_config_test.go | 2 ++ .../fixer/rules/gen_phpdoc_tags_test.go | 4 +++ .../fixer/rules/gen_phpdoc_var_test.go | 2 ++ blink/internal/fixer/rules/gen_types_test.go | 3 ++ blink/internal/fixer/rules/gen_ws_test.go | 3 ++ ...al_phpdoc_annotation_remove_config_test.go | 1 + .../general_phpdoc_annotation_remove_test.go | 1 + .../fixer/rules/imports_order_config_test.go | 3 ++ .../fixer/rules/imports_unused_test.go | 3 ++ .../fixer/rules/indentation_braces_test.go | 4 +++ blink/internal/fixer/rules/is_null_test.go | 2 ++ .../rules/lambda_not_used_import_test.go | 1 + .../method_argument_space_config_test.go | 1 + .../method_argument_space_phpcsfixer_test.go | 1 + .../fixer/rules/method_argument_space_test.go | 2 ++ .../fixer/rules/modifier_keywords_test.go | 1 + blink/internal/fixer/rules/more_rules_test.go | 7 +++++ .../rules/new_with_parentheses_config_test.go | 1 + .../no_alternative_syntax_config_test.go | 1 + .../fixer/rules/no_alternative_syntax_test.go | 1 + .../no_blank_line_between_imports_test.go | 1 + .../rules/no_break_comment_config_test.go | 1 + .../fixer/rules/no_break_comment_test.go | 1 + .../fixer/rules/no_superfluous_elseif_test.go | 1 + .../no_superfluous_phpdoc_tags_config_test.go | 2 ++ .../rules/no_superfluous_phpdoc_tags_test.go | 2 ++ .../rules/no_unneeded_braces_config_test.go | 1 + .../fixer/rules/no_unneeded_braces_test.go | 1 + ...nneeded_control_parentheses_config_test.go | 1 + ...unreachable_default_argument_value_test.go | 1 + .../no_useless_concat_operator_config_test.go | 1 + .../no_useless_nullsafe_operator_test.go | 1 + .../fixer/rules/offset_config_test.go | 1 + .../fixer/rules/operator_linebreak_test.go | 1 + .../internal/fixer/rules/parity_5bugs_test.go | 4 +++ blink/internal/fixer/rules/percs_test.go | 2 ++ .../internal/fixer/rules/phpdoc_align_test.go | 1 + .../fixer/rules/phpdoc_batch_config_test.go | 2 ++ .../internal/fixer/rules/phpdoc_batch_test.go | 9 ++++++ .../fixer/rules/phpdoc_config_test.go | 1 + .../phpdoc_no_useless_inheritdoc_test.go | 1 + .../fixer/rules/phpdoc_separation_test.go | 1 + blink/internal/fixer/rules/phpdoc_test.go | 5 +++ .../fixer/rules/phpdoc_to_comment_test.go | 1 + .../fixer/rules/phpunit_method_casing_test.go | 3 ++ .../fixer/rules/rector_regression_test.go | 2 ++ blink/internal/fixer/rules/regression_test.go | 4 +++ ...e_param_description_duplicate_name_test.go | 4 +++ .../remove_useless_default_comment_test.go | 2 ++ .../fixer/rules/return_ternary_test.go | 2 ++ .../return_type_declaration_config_test.go | 1 + blink/internal/fixer/rules/rules_test.go | 31 +++++++++++++++++++ .../fixer/rules/self_accessor_test.go | 1 + .../fixer/rules/self_static_accessor_test.go | 1 + blink/internal/fixer/rules/source_test.go | 1 + .../space_after_comma_here_now_doc_test.go | 1 + .../space_after_semicolon_config_test.go | 1 + ...standalone_line_in_multiline_array_test.go | 1 + ...alone_line_plain_constructor_param_test.go | 1 + .../standalone_line_promoted_property_test.go | 1 + .../standalone_line_required_param_test.go | 1 + ...alone_line_symfony_attribute_param_test.go | 1 + .../statement_indentation_config_test.go | 3 ++ .../statement_indentation_phpcsfixer_test.go | 1 + .../statement_indentation_regression_test.go | 1 + .../rules/string_notation_config_test.go | 1 + .../fixer/rules/symplify_docblock_test.go | 11 +++++++ .../rules/ternary_to_null_coalescing_test.go | 1 + blink/internal/fixer/rules/tier2_test.go | 4 +++ .../internal/fixer/rules/token_batch_test.go | 7 +++++ .../fixer/rules/trailing_comma_config_test.go | 1 + .../rules/visibility_required_config_test.go | 1 + .../fixer/rules/yoda_style_config_test.go | 3 ++ .../fixer/rules/yoda_style_phpcsfixer_test.go | 1 + blink/internal/fixer/rules/yoda_style_test.go | 2 ++ 135 files changed, 333 insertions(+) diff --git a/blink/internal/fixer/rules/add_missing_param_name_test.go b/blink/internal/fixer/rules/add_missing_param_name_test.go index 10e204735a..ad1808298d 100644 --- a/blink/internal/fixer/rules/add_missing_param_name_test.go +++ b/blink/internal/fixer/rules/add_missing_param_name_test.go @@ -4,6 +4,7 @@ import "testing" // TestAddMissingParamName adds the positional variable name to a type-only @param. func TestAddMissingParamName(t *testing.T) { + t.Parallel() src := "}>,\n * timeless: list}>\n * } $messages\n */\n function f(array $messages) {}\n}\n" if got, changed := apply(t, AddMissingParamName{}, src); changed || got != src { t.Fatalf("multi-line array-shape param with name must be left alone: changed=%v got=%q", changed, got) diff --git a/blink/internal/fixer/rules/array_indentation_test.go b/blink/internal/fixer/rules/array_indentation_test.go index fbac89beb8..cc98621a7b 100644 --- a/blink/internal/fixer/rules/array_indentation_test.go +++ b/blink/internal/fixer/rules/array_indentation_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestArrayIndentation(t *testing.T) { + t.Parallel() f := ArrayIndentation{} // nested array under-indented: each level indented exactly once diff --git a/blink/internal/fixer/rules/array_list_item_newline_test.go b/blink/internal/fixer/rules/array_list_item_newline_test.go index f4fdc9b465..042abf0672 100644 --- a/blink/internal/fixer/rules/array_list_item_newline_test.go +++ b/blink/internal/fixer/rules/array_list_item_newline_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestArrayListItemNewline(t *testing.T) { + t.Parallel() f := ArrayListItemNewline{} // associative single-line array -> one item per line, trailing comma, [] on own lines diff --git a/blink/internal/fixer/rules/array_notation_config_test.go b/blink/internal/fixer/rules/array_notation_config_test.go index 03eec4cc3b..49af193814 100644 --- a/blink/internal/fixer/rules/array_notation_config_test.go +++ b/blink/internal/fixer/rules/array_notation_config_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestArrayNotationConfigCases(t *testing.T) { + t.Parallel() cases := []struct { name string rule fixerRule diff --git a/blink/internal/fixer/rules/array_opener_and_closer_newline_test.go b/blink/internal/fixer/rules/array_opener_and_closer_newline_test.go index 294d694159..38ed700db2 100644 --- a/blink/internal/fixer/rules/array_opener_and_closer_newline_test.go +++ b/blink/internal/fixer/rules/array_opener_and_closer_newline_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestArrayOpenerAndCloserNewline(t *testing.T) { + t.Parallel() f := ArrayOpenerAndCloserNewline{} // associative array: "[" and "]" go on their own lines, items untouched diff --git a/blink/internal/fixer/rules/batch10_test.go b/blink/internal/fixer/rules/batch10_test.go index 33df97e624..8d01dc6752 100644 --- a/blink/internal/fixer/rules/batch10_test.go +++ b/blink/internal/fixer/rules/batch10_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestTrailingCommaInMultiline(t *testing.T) { + t.Parallel() got, changed := apply(t, TrailingCommaInMultiline{}, " b -> c();") if want := "b->c();"; !changed || got != want { t.Fatalf("changed=%v got=%q want=%q", changed, got, want) @@ -50,6 +54,7 @@ func TestObjectOperatorWithoutWhitespace(t *testing.T) { } func TestNativeFunctionCasing(t *testing.T) { + t.Parallel() got, changed := apply(t, NativeFunctionCasing{}, "foo()\n->bar()\n ->baz();\n") if want := "foo()\n ->bar()\n ->baz();\n"; !changed || got != want { t.Fatalf("changed=%v got=%q want=%q", changed, got, want) diff --git a/blink/internal/fixer/rules/batchD_test.go b/blink/internal/fixer/rules/batchD_test.go index 3a658d5ca5..f8f084a5bb 100644 --- a/blink/internal/fixer/rules/batchD_test.go +++ b/blink/internal/fixer/rules/batchD_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestSimplifiedNullReturn(t *testing.T) { + t.Parallel() // no return type -> simplified got, changed := apply(t, SimplifiedNullReturn{}, "{$prop}" is dynamic access, not a control block: no space inserted if _, changed := apply(t, BracesPosition{}, "{$prop} != $v) {\n}"); changed { t.Fatal("dynamic property access brace must not get a space") @@ -52,6 +56,7 @@ func TestBracesPositionDynamicAccessLeftAlone(t *testing.T) { } func TestClassifyBrace(t *testing.T) { + t.Parallel() cases := []struct { src string want braceKind @@ -80,6 +85,7 @@ func TestClassifyBrace(t *testing.T) { // a trait adaptation block "use T { ... }" is not a class/function body func TestClassifyTraitBlockIsOther(t *testing.T) { + t.Parallel() s := lexStream(" $b) {}") if want := " aligned under the first "*" got, changed := apply(t, AlignMultilineComment{}, " 1;") @@ -39,6 +41,7 @@ func TestFunctionDeclarationClosureFnSpacing(t *testing.T) { } func TestFunctionDeclarationTrailingCommaSingleLine(t *testing.T) { + t.Parallel() // trailing_comma_single_line=false: drop the trailing comma in a single-line signature cfg := FunctionDeclaration{}.WithConfig(map[string]any{"trailing_comma_single_line": false}) got, changed := apply(t, cfg, " // comment @@ -62,6 +63,7 @@ func TestGen4ASingleLineCommentStyle(t *testing.T) { } func TestGen4ANoNullPropertyInitialization(t *testing.T) { + t.Parallel() f := NoNullPropertyInitialization{} // untyped property loses its null default @@ -126,6 +128,7 @@ func TestGen4ANoNullPropertyInitialization(t *testing.T) { // TestGen4ASourceURL verifies each SourceURL matches SourceURLFor(Name()). func TestGen4ASourceURL(t *testing.T) { + t.Parallel() for _, f := range []fixer.Fixer{SingleLineCommentStyle{}, NoNullPropertyInitialization{}} { if got, want := f.SourceURL(), fixer.SourceURLFor(f.Name()); got != want { t.Errorf("%s: SourceURL %q != SourceURLFor %q", f.Name(), got, want) diff --git a/blink/internal/fixer/rules/gen4_b_test.go b/blink/internal/fixer/rules/gen4_b_test.go index cb23b72cd5..b2fece820b 100644 --- a/blink/internal/fixer/rules/gen4_b_test.go +++ b/blink/internal/fixer/rules/gen4_b_test.go @@ -7,6 +7,7 @@ import ( ) func TestGen4BExplicitIndirectVariable(t *testing.T) { + t.Parallel() cases := []struct { src, want string changed bool @@ -52,6 +53,7 @@ func TestGen4BExplicitIndirectVariable(t *testing.T) { } func TestGen4BSourceURLs(t *testing.T) { + t.Parallel() fixers := []fixer.Fixer{ ExplicitIndirectVariable{}, } diff --git a/blink/internal/fixer/rules/gen4_phpdoc_config_test.go b/blink/internal/fixer/rules/gen4_phpdoc_config_test.go index d443adbf2f..8eaecbfeb6 100644 --- a/blink/internal/fixer/rules/gen4_phpdoc_config_test.go +++ b/blink/internal/fixer/rules/gen4_phpdoc_config_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestPhpdocLineSpanConfig(t *testing.T) { + t.Parallel() single := " $this @@ -67,6 +68,7 @@ func TestGen5PhpdocMiscReturnSelfReference(t *testing.T) { } func TestGen5PhpdocMiscReturnSelfReferenceSourceURL(t *testing.T) { + t.Parallel() var f fixer.Fixer = PhpdocReturnSelfReference{} if got, want := f.SourceURL(), fixer.SourceURLFor(f.Name()); got != want { t.Fatalf("SourceURL %q, want %q", got, want) diff --git a/blink/internal/fixer/rules/gen5_phpdoc_order_test.go b/blink/internal/fixer/rules/gen5_phpdoc_order_test.go index 4dc4de06cd..f8b0abeaba 100644 --- a/blink/internal/fixer/rules/gen5_phpdoc_order_test.go +++ b/blink/internal/fixer/rules/gen5_phpdoc_order_test.go @@ -7,6 +7,7 @@ import ( ) func TestGen5PhpdocOrderTypesOrder(t *testing.T) { + t.Parallel() f := PhpdocTypesOrder{} // null moves to the end, other members keep order: string|null|int -> string|int|null @@ -56,6 +57,7 @@ func TestGen5PhpdocOrderTypesOrder(t *testing.T) { } func TestGen5PhpdocOrderVarAnnotation(t *testing.T) { + t.Parallel() f := PhpdocVarAnnotationCorrectOrder{} // swapped single-line @var @@ -90,6 +92,7 @@ func TestGen5PhpdocOrderVarAnnotation(t *testing.T) { } func TestGen5PhpdocOrderSourceURLs(t *testing.T) { + t.Parallel() for _, f := range []fixer.Fixer{PhpdocTypesOrder{}, PhpdocVarAnnotationCorrectOrder{}} { if got, want := f.SourceURL(), fixer.SourceURLFor(f.Name()); got != want { t.Fatalf("%s SourceURL %q, want %q", f.Name(), got, want) diff --git a/blink/internal/fixer/rules/gen6_phpdoc_test.go b/blink/internal/fixer/rules/gen6_phpdoc_test.go index 9e422daa38..e8ebf3efdc 100644 --- a/blink/internal/fixer/rules/gen6_phpdoc_test.go +++ b/blink/internal/fixer/rules/gen6_phpdoc_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoAliasLanguageConstructCall(t *testing.T) { + t.Parallel() got, changed := apply(t, NoAliasLanguageConstructCall{}, "\n 1,\n];") if want := " 1,\n];"; !changed || got != want { t.Fatalf("after: changed=%v got=%q want=%q", changed, got, want) @@ -88,6 +91,7 @@ func TestGenArraysNoMultilineWhitespaceAroundDoubleArrow(t *testing.T) { // TestGenArraysSourceURLs verifies every SourceURL matches SourceURLFor(Name()). func TestGenArraysSourceURLs(t *testing.T) { + t.Parallel() fixers := []fixerpkg.Fixer{ NoWhitespaceInEmptyArray{}, NormalizeIndexBrace{}, @@ -102,6 +106,7 @@ func TestGenArraysSourceURLs(t *testing.T) { // TestGenArraysIdempotent guarantees a second pass is a no-op. func TestGenArraysIdempotent(t *testing.T) { + t.Parallel() fixers := []fixerRule{ NoWhitespaceInEmptyArray{}, NormalizeIndexBrace{}, diff --git a/blink/internal/fixer/rules/gen_control_test.go b/blink/internal/fixer/rules/gen_control_test.go index 1f64e81fd3..14a5c0c99b 100644 --- a/blink/internal/fixer/rules/gen_control_test.go +++ b/blink/internal/fixer/rules/gen_control_test.go @@ -7,6 +7,7 @@ import ( ) func TestGenControlSwitchContinueToBreak(t *testing.T) { + t.Parallel() cases := []struct { src string want string @@ -106,6 +107,7 @@ func TestGenControlSwitchContinueToBreak(t *testing.T) { // TestGenControlSourceURLs verifies each SourceURL matches SourceURLFor(Name()). func TestGenControlSourceURLs(t *testing.T) { + t.Parallel() for _, f := range []fixer.Fixer{SwitchContinueToBreak{}} { if got, want := f.SourceURL(), fixer.SourceURLFor(f.Name()); got != want { t.Errorf("%s: SourceURL %q != SourceURLFor %q", f.Name(), got, want) diff --git a/blink/internal/fixer/rules/gen_imports_test.go b/blink/internal/fixer/rules/gen_imports_test.go index d522770a32..262d9fe671 100644 --- a/blink/internal/fixer/rules/gen_imports_test.go +++ b/blink/internal/fixer/rules/gen_imports_test.go @@ -7,6 +7,7 @@ import ( ) func TestGenImportsNoUnneededImportAlias(t *testing.T) { + t.Parallel() got, changed := apply(t, NoUnneededImportAlias{}, "\nHi\n\n" if _, changed := apply(t, NoAlternativeSyntax{}, src); !changed { t.Fatal("default should fix inline HTML code") diff --git a/blink/internal/fixer/rules/no_alternative_syntax_test.go b/blink/internal/fixer/rules/no_alternative_syntax_test.go index 4e3e5ca5aa..e18cf2135d 100644 --- a/blink/internal/fixer/rules/no_alternative_syntax_test.go +++ b/blink/internal/fixer/rules/no_alternative_syntax_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoAlternativeSyntax(t *testing.T) { + t.Parallel() cases := []struct { src string want string diff --git a/blink/internal/fixer/rules/no_blank_line_between_imports_test.go b/blink/internal/fixer/rules/no_blank_line_between_imports_test.go index fec7108bbc..95a7e9f412 100644 --- a/blink/internal/fixer/rules/no_blank_line_between_imports_test.go +++ b/blink/internal/fixer/rules/no_blank_line_between_imports_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoBlankLineBetweenImports(t *testing.T) { + t.Parallel() f := NoBlankLineBetweenImports{} // blank lines between consecutive imports collapse; the namespace gap stays diff --git a/blink/internal/fixer/rules/no_break_comment_config_test.go b/blink/internal/fixer/rules/no_break_comment_config_test.go index 63e88e7fae..312c5c26c4 100644 --- a/blink/internal/fixer/rules/no_break_comment_config_test.go +++ b/blink/internal/fixer/rules/no_break_comment_config_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoBreakCommentConfig(t *testing.T) { + t.Parallel() src := " elseif becomes if diff --git a/blink/internal/fixer/rules/no_superfluous_phpdoc_tags_config_test.go b/blink/internal/fixer/rules/no_superfluous_phpdoc_tags_config_test.go index 59bfc82531..c170a835f2 100644 --- a/blink/internal/fixer/rules/no_superfluous_phpdoc_tags_config_test.go +++ b/blink/internal/fixer/rules/no_superfluous_phpdoc_tags_config_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoSuperfluousPhpdocTagsConfig(t *testing.T) { + t.Parallel() // default keeps "@param mixed" on an untyped parameter (allow_mixed behavior) mixed := " removed @@ -96,6 +97,7 @@ func TestNoSuperfluousPhpdocTags(t *testing.T) { } func TestNoSuperfluousPhpdocTagsSourceURL(t *testing.T) { + t.Parallel() f := NoSuperfluousPhpdocTags{} if got, want := f.SourceURL(), fixer.SourceURLFor(f.Name()); got != want { t.Fatalf("SourceURL %q, want %q", got, want) diff --git a/blink/internal/fixer/rules/no_unneeded_braces_config_test.go b/blink/internal/fixer/rules/no_unneeded_braces_config_test.go index 7302ab51cc..f59f1fb2a3 100644 --- a/blink/internal/fixer/rules/no_unneeded_braces_config_test.go +++ b/blink/internal/fixer/rules/no_unneeded_braces_config_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoUnneededBracesConfig(t *testing.T) { + t.Parallel() src := "parentMethod(); }\n}\n") diff --git a/blink/internal/fixer/rules/offset_config_test.go b/blink/internal/fixer/rules/offset_config_test.go index 3c3dbf873e..6daf89ca4a 100644 --- a/blink/internal/fixer/rules/offset_config_test.go +++ b/blink/internal/fixer/rules/offset_config_test.go @@ -3,6 +3,7 @@ package rules import "testing" func TestNoSpacesAroundOffsetConfig(t *testing.T) { + t.Parallel() src := " $x;") if want := " $x;"; !changed || got != want { t.Fatalf("changed=%v got=%q want=%q", changed, got, want) @@ -13,6 +14,7 @@ func TestArrowFnSpacing(t *testing.T) { } func TestPhpdocTypesGenericsAndConst(t *testing.T) { + t.Parallel() // a pseudo-type keyword inside generics is lowercased got, changed := apply(t, PhpdocTypes{}, "\n */\nclass A {}") if want := "\n */\nclass A {}"; !changed || got != want { @@ -25,6 +27,7 @@ func TestPhpdocTypesGenericsAndConst(t *testing.T) { } func TestNoBlankLinesAfterPhpdocKeepsFileDocblock(t *testing.T) { + t.Parallel() // a file-level docblock before "declare" keeps its blank line src := " @var got, changed := apply(t, PhpdocNoAliasTag{}, "%command.name% command is send a channel broadcast to pending contacts.\n\nphp %command.full_name% --channel=email --id=3\nTXT\n)]\nclass A {}\n" got, changed := apply(t, RemoveUselessDefaultComment{}, src) if changed || got != src { @@ -11,6 +12,7 @@ func TestRemoveUselessDefaultCommentKeepsHeredocBlankLine(t *testing.T) { } func TestRemoveUselessDefaultCommentStillRemovesTodo(t *testing.T) { + t.Parallel() src := "1, 'y' => 2];") if want := " 1, 'y' => 2];"; !changed || got != want { t.Fatalf("changed=%v got=%q want=%q", changed, got, want) @@ -91,6 +97,7 @@ func TestBinaryOperatorSpaces(t *testing.T) { } func TestConcatSpace(t *testing.T) { + t.Parallel() got, changed := apply(t, ConcatSpace{}, "bar ();") if want := "bar();"; !changed || got != want { t.Fatalf("changed=%v got=%q want=%q", changed, got, want) @@ -202,6 +216,7 @@ func TestNoSpacesAfterFunctionName(t *testing.T) { } func TestNoSpacesInsideParenthesis(t *testing.T) { + t.Parallel() got, changed := apply(t, NoSpacesInsideParenthesis{}, "\n") if want := "{$key}") in a multiline ternary must not be read // as a block/statement end; the ":" line stays aligned with the "?" line src := "condition\n ? $this->target->{$key}\n : $this->target;\n }\n}\n" @@ -30,6 +32,7 @@ func TestStatementIndentationTernaryDynamicMember(t *testing.T) { } func TestStatementIndentationNamedArgumentKeyword(t *testing.T) { + t.Parallel() // a reserved word used as a named-argument label ("default:", "case:") is not // a switch case; it must not indent the statements that follow the call src := "