Goodbye Perl by T-Gro · Pull Request #19226 · dotnet/fsharp

9 min read Original article ↗

Conversation

Create MIGRATION_BLOCKERS.md and TEST_FRAMEWORK_ADDITIONS.md in
tests/FSharp.Compiler.ComponentTests/ to track issues discovered
during the fsharpqa migration process.
- Added 15 test methods from fsharpqa/Source/Diagnostics/async/env.lst
- Git-moved IncompleteMatchInAsync01.fs to resources/tests/Diagnostics/async/
- All tests use existing DirectoryAttribute pattern with typecheck/compile
- Tests cover async diagnostics: LetBangNonAsync, MissingIgnore, MissingReturnBangForLoop, ReturnBangNonAsync variants, UsingReturnInAWhileLoop, UsingReturnInIfThenElse, IncompleteMatchInAsync
- 4 pre-existing tests (MissingBangForLoop01/02, ReturnBangNonAsync_IfThenElse, UseBindingWrongForm01) retained - these test files in resources/ not in env.lst
- Git-moved 37 source files to resources/tests/Diagnostics/NONTERM/
- Created Diagnostics/NONTERM.fs with 36 test methods (matching env.lst)
- Added Compile Include to FSharp.Compiler.ComponentTests.fsproj
- Tests verify parser error messages don't contain internal NONTERM tokens
- Move 12 source files from tests/fsharpqa/Source/Diagnostics/ParsingAtEOF/
  to tests/FSharp.Compiler.ComponentTests/resources/tests/Diagnostics/ParsingAtEOF/
- Create ParsingAtEOF.fs with 11 test methods for parsing EOF diagnostics
- Tests cover: while, for, if, match, try, type definitions at EOF
- Git-moved 25 source files from tests/fsharpqa/Source/Diagnostics/General/
  to tests/FSharp.Compiler.ComponentTests/resources/tests/Diagnostics/General/
- Updated General.fs with 25 new test methods (26 total including existing)
- Tests cover formatting errors, mutating immutable, operator redefinition,
  generic type instantiation warnings, and other general diagnostics
- All 26 tests pass
Moved 6 files (W_redefineOperator03.fs through W_redefineOperator10.fs) from
tests/fsharpqa/Source/Diagnostics/General/ to
tests/FSharp.Compiler.ComponentTests/resources/tests/Diagnostics/General/
using git mv to preserve history.

Added corresponding test methods to General.fs following the existing pattern
with --test:ErrorRanges, typecheck, and warning code 0086 assertions.
Move 6 test files from fsharpqa to resources/tests/Diagnostics/General:
- E_matrix_class01.fs (FS0039)
- E_matrix_interface01.fs (FS0039)
- E_matrix_LetBinding01.fs (FS0039)
- E_matrix_struct01.fs (FS0039)
- E_ExpressionHasType_FullPath01.fs (FS0001)
- W_GenericTypeProvideATypeInstantiation01.fs (FS1125)

Add corresponding test methods in General.fs.
- Migrate E_ObjectConstructorAndTry01.fs to component tests
- Migrate E_ObjectConstructorAndTry02.fs to component tests
- Migrate X-DontWarnOnImplicitModule01.fsx to component tests (asFsx)
- Migrate X-DontWarnOnImplicitModule01.fsscript to component tests (asFsx)

All 4 files moved via git mv to preserve history.
4 test methods added to General.fs.
Move 5 files from tests/fsharpqa/Source/Diagnostics/General/ to
tests/FSharp.Compiler.ComponentTests/resources/tests/Diagnostics/General/:

- E_AreYouMissingAnArgumentToAFunction01.fs
- E_AreYouMissingAnArgumentToAFunction01b.fs
- E_ConsiderAddingSealedAttribute01.fsi
- E_ConsiderAddingSealedAttribute01.fs
- E_LiteralEnumerationMustHaveType01.fs

Add 4 test methods to Diagnostics/General.fs:
- E_AreYouMissingAnArgumentToAFunction01_fs (FS0001)
- E_AreYouMissingAnArgumentToAFunction01b_fs (FS0001)
- E_ConsiderAddingSealedAttribute01_fsi_fs (FS0297, multi-file)
- E_LiteralEnumerationMustHaveType01_fs (FS0886)

The sealed attribute test uses withAdditionalSourceFile for multi-file
compilation of fsi+fs pair.
- Move E_IndexedPropertySetter01.fs (FS0554 invalid declaration syntax)
- Move E_PropertyIsNotReadable01.fs (FS0807 property not readable)
- Move E_MemberConstraintsWithSpecialStatus01.fs (FS0077 special Pow member)
- Move E_FoundInPowerPack_Matrix01.fs (FS0039 Matrix not defined)
- Move E_UnexpectedKeywordAs01.fs (FS0010 unexpected as keyword)
- Add 5 corresponding test methods to General.fs
Move 6 parsing error test files to resources/tests/Diagnostics/General/:
- E_IncompleteConstruct01.fs (FS3567 expecting member body)
- E_IncompleteConstruct01b.fs (FS3567 expecting member body)
- E_UnexpectedKeyworkWith01.fs (FS0010 unexpected 'with')
- E_MemberObjectctorTakeGiven.fs (FS0502 wrong type arguments)
- E_StructMustHaveAtLeastOneField.fs (struct can now be empty)
- E_UnexpectedSymbol01.fs (FS0010, FS0588 unexpected symbol)

Add 6 corresponding test methods to General.fs using typecheck and
shouldFail patterns.
Move 6 test files to resources/tests/Diagnostics/General/:
- W_OverrideImplementationInAugmentation01a.fs
- W_OverrideImplementationInAugmentation02b.fs
- W_OverrideImplementationInAugmentation03a.fs
- W_OverrideImplementationInAugmentation03b.fs
- E_Quotation_UnresolvedGenericConstruct01.fs
- E_InvalidObjectExpression01.fs

Add 6 corresponding test methods in General.fs.
Move 10 test files to resources/tests/Diagnostics/General/:
- W_CreateIDisposable.fs (FS0760)
- W_FailwithRedundantArgs.fs (FS3189)
- W_FailwithfRedundantArgs.fs (FS3189)
- W_RaiseRedundantArgs.fs (FS3189)
- W_InvalidArgRedundantArgs.fs (FS3189)
- W_NullArgRedundantArgs.fs (FS3189)
- W_InvalidOpRedundantArgs.fs (FS3189)
- W_LowercaseLiteralIgnored.fs (FS3190)
- W_LowercaseLiteralNotIgnored.fs (FS0026)
- W_IndexedPropertySetter01.fs (FS0191)

Add 10 corresponding test methods to General.fs.
The E_MissingSourceFile01-04.fs tests cannot be migrated to
ComponentTests because they test CLI-specific error handling
for missing source files. The test infrastructure uses in-memory
compilation where source content is provided directly, making
'file not found' scenarios impossible to test.

- Added E_MissingSourceFile tests to MIGRATION_BLOCKERS.md
- All env.lst tests now accounted for (72 migrated, 4 blocked)
- Removed obsolete W_IndexedPropertySetter01 test (FS0191 no longer exists)
Delete remaining legacy test files after migration:
- E_MissingSourceFile01-04.fs: Documented as migration blockers (CLI-specific tests)
- W_PassingResxToCompilerIsDeprecated01.fs/.resx: CLI-specific test
- env.lst: Legacy test manifest

These tests cannot be migrated to FSharp.Compiler.ComponentTests as they
require CLI invocation with actual file paths. The decision to skip
migration is documented in MIGRATION_BLOCKERS.md.
Delete async/, NONTERM/, and ParsingAtEOF/ from tests/fsharpqa/Source/Diagnostics/
All tests have been successfully migrated to tests/FSharp.Compiler.ComponentTests/
- async: 19 tests
- NONTERM: 36 tests
- ParsingAtEOF: 12 tests

The source files and env.lst files are no longer needed as the tests run from
the resources/ folder in the component tests project.
Summary of FSharpQA Diagnostics Migration:
- Total test methods migrated: 138
  - async: 19 tests
  - NONTERM: 36 tests
  - ParsingAtEOF: 11 tests
  - General: 72 tests
- Total resource files moved: 141
- Total test code: 1,518 lines of F#
- Legacy fsharpqa/Source/Diagnostics folder: cleaned up
- All tests passing with existing infrastructure
…ests

Migrated folders:
- dumpAllCommandLineOptions (2 tests)
- gccerrors (1 test)
- standalone (1 test - simplified from original multi-file test)
- staticlink (1 test - simplified from original multi-file test)
- tailcalls (6 tests)
- target (2 tests)
- tokenize (2 tests)

The nologo folder was skipped as it requires complex baseline comparison.

Tests now use the FileInlineData pattern with source files in the same
directory as the test files. Updated test.lst to comment out migrated
folders.
- Git-move flaterrors source files to resources/tests/CompilerOptions/fsc/flaterrors/
- Rename flaterrors.fs to Flaterrors.fs (capital F)
- Git-move optimize source files to resources/tests/CompilerOptions/fsc/optimize/
- Create Optimize.fs with tests for --optimize, --optimize+, -O, -O+, -O-, --optimize-
- Update FSharp.Compiler.ComponentTests.fsproj with new paths
- Comment out flaterrors and optimize in test.lst
- Delete fsharpqa/Source/CompilerOptions/fsc/flaterrors and optimize folders
…Tests

Migrate tests from legacy fsharpqa Perl-based test suite:
- lib (15 tests): --lib/-I option validation, syntax variants, errors, warnings
- out (11 tests): --out option validation, syntax, case-sensitivity
- responsefile (7 tests): @ response file handling, comments, errors

All tests use inline source strings following existing patterns in the codebase.
Tests cover option syntax validation, error codes FS0243/FS0224/FS0211/FS3194/FS3195.

Removed original fsharpqa folders as tests are now in ComponentTests.
- Migrate platform tests (~16 tests for invalid platform values)
- Migrate Removed/deprecated options tests (~55 tests)
- Fix deprecated option tests to use ignoreWarnings for proper success checking
- Update --sscli from deprecated to removed (behavior changed)
- Note: Some FSI deprecated options cannot be tested via compiler service
  as they are silently ignored - they were only checked when running FSI directly
- Delete fsharpqa/Source/CompilerOptions/fsc/platform and Removed folders
- Add Pdb.fs with WindowsOnly tests (9 tests migrated from pdb folder)
- Add Subsystemversion.fs with DesktopOnly tests (10 tests migrated)
- Delete legacy fsharpqa/Source/CompilerOptions/fsc/pdb directory
- Delete legacy fsharpqa/Source/CompilerOptions/fsc/subsystemversion directory

Note: pdb03.fsx test (FSI mode) cannot be migrated - requires FSIMODE=PIPE
which tests actual FSI execution, not fsc compilation.
- Add FactForWINDOWSAttribute to FSharp.Test.Utilities for Windows-only tests
- Replace runtime platform checks in Pdb.fs with FactForWINDOWS attribute
- Add [<Trait("Category", "WindowsOnly")>] to Pdb module
- Add [<Trait("Category", "DesktopOnly")>] to Subsystemversion module
- Add missing pdb tests for subdirectory paths and embedded debug scenarios
- All 11 pdb tests and 10 subsystemversion tests properly annotated
- Add Langversion.fs with 3 tests for invalid langversion arguments
- Add Nologo.fs with 2 tests for FSI --nologo option
- Delete original fsharpqa langversion and nologo directories

All 5 tests pass.
…sion tests

These 6 tests cannot be migrated to the component test infrastructure
because FsiEvaluationSession.Create throws StopProcessingExn when:
- Help options (-?, --help, /?) are passed
- Unrecognized options (--highentropyva+, --subsystemversion:X.XX) are passed

The fsharpqa source folders are intentionally preserved as these tests
represent known infrastructure limitations.
- Update summary table to count 7 tests (was 6)
- Add explicit section for --langversion:? as 4th blocker category
- Clarify help options list (-?, --help, /?) in summary
- Update Option 3 (Keep in Legacy Suite) to reference 7 tests

The --langversion:? option displays help for available language versions
and exits, triggering the same StopProcessingExn blocker as other help
options.
…Tests

- Migrated 18 source files to resources/tests/Conformance/LexicalFiltering/
- Created new test files:
  - Basic/Basic.fs (4 tests for ByExample and OffsideExceptions)
  - LexicalAnalysisOfTypeApplications/LexicalAnalysisOfTypeApplications.fs (1 test)
- Updated existing test files:
  - HashLight/HashLight.fs (added 10 tests)
  - HighPrecedenceApplication/HighPrecedenceApplication.fs (added 3 tests)
- Deleted fsharpqa/Source/Conformance/LexicalFiltering/ folder
- All 47 LexicalFiltering tests pass
- Migrate 10 signature conformance tests from legacy Perl-based test suite
- Create tests/FSharp.Compiler.ComponentTests/Conformance/Signatures/Signatures.fs
- Git-move 19 source files to resources/tests/Conformance/Signatures/
- Delete tests/fsharpqa/Source/Conformance/Signatures/ folder

Tests cover:
- Literal definitions in signatures (Literal01)
- Internal accessibility verification (InternalAccessibility01-03)
- Interface hidden by signature (ImplementsComparable, MissingMethodInImplementation01)
- Attribute matching (AttributeMatching01)
- Struct constructor/naming validation (E_StructConstructor01, E_StructWithNameConflict01-02)
…ComponentTests

Migrate 11 tests from the legacy fsharpqa Perl-based test suite:
- CallerInfo tests (10): CallerLineNumber, CallerFilePath, CallerMemberName
  validation and error cases for wrong types, non-optional args
- ThreadStatic test (1): W_Deprecated01 for deprecated let binding warning

Note: ViaInteractive.fsx tests (EXEC/PIPE modes) were not migrated as they
require platform-specific path checks that don't translate to in-memory
compilation. The CallerInfo functionality is covered by other tests.

Created:
- tests/FSharp.Compiler.ComponentTests/Conformance/SpecialAttributesAndTypes/CallerInfo.fs
- tests/FSharp.Compiler.ComponentTests/Conformance/SpecialAttributesAndTypes/ThreadStatic.fs

Deleted:
- tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/ (entire folder)
Add test methods to SymbolicOperators.fs covering:
- 12 success tests for QMark (?) operator precedence, nesting, and arguments
- 1 error test (E_QMarkGeneric) for FS0717: Unexpected type arguments

Test files migrated:
- QMarkSimple.fs, QMarkNested.fs, QMarkArguments.fs
- QMarkAssignSimple.fs, QMarkExpressionAsArgument.fs
- QMarkExpressionAsArgument2.fs, QMarkPrecedenceArray.fs
- QMarkPrecedenceCurrying.fs, QMarkPrecedenceInArrays.fs
- QMarkPrecedenceMethodCall.fs, QMarkPrecedenceMethodCallSpace.fs
- QMarkPrecedenceSpace.fs, E_QMarkGeneric.fs

All 13 tests pass.
Added 17 tests for OCaml-style (* *) comment syntax:
- Basic OCaml-style comments (ocamlstyle001, ocamlstyle002)
- Nested comments (ocamlstyle_nested001-005)
- Error cases for malformed nested comments (E_ocamlstyle_nested006-007)
- Embedded strings within comments (embeddedString001-004, E_embeddedString005)
- Escape characters in comments (escapeCharsInComments001-002)
- Incomplete comment errors (E_IncompleteComment01-02)
- XML doc comments and string literal edge cases

All 38 Comments tests pass.
All 6 originally identified gaps have been migrated:
- TypeExtensions/optional: 12 tests in Optional.fs
- Import/em_csharp: 10+ tests in ImportTests.fs
- Import/FamAndAssembly: 29+ tests in ImportTests.fs
- SymbolicOperators/QMark: 17 tests in SymbolicOperators.fs
- NumericLiterals/casing: 21 tests in NumericLiterals.fs
- Comments/ocamlstyle: 21 tests in Comments.fs

Total: 3,600+ test methods migrated (100% complete)
…on 4.6/4.7 resource files, and update tests
- Delete NameOf.fs and all E_NameOf*.fs resource files (11 skipped tests)
- Delete 3 skipped tests from ComputationExpressions.fs + resource files
- Delete skipped test from ObjectExpressions.fs + resource file
- Update E_Abbreviation test to use withLangVersion80
- Update OnUnionWithCaseOfSameName2 test to use withLangVersion80

All withLangVersion(46|47|50|60|70) usages removed.
- Remove --langversion:5.0 from TypesAndTypeConstraints tests (6 occurrences)
- Remove --langversion:5.0 from InterfaceTypes tests (6 occurrences)
- Delete E_QuoteDynamic01 version-gate test (F# 4.6 specific behavior)
- Update legacy comments in RequireQualifiedAccess, ObjectConstructors, and
  NamespacesFragmentsAndImplementationFiles

All modified test areas verified passing:
- TypesAndTypeConstraints: 189 passed
- InterfaceTypes: 32 passed
- ExpressionQuotations: 107 passed
- Other modified files: 8 passed
…5.0)

- Removed --langversion:5.0 from 5 tests in NONTERM.fs
- Added NONTERM.fs to project file (was previously not included)
- All 36 NONTERM tests pass
- All 91 Diagnostics tests pass
- Sync Compiler.fs with main (useRawOptions, FsiArgs, TypeForwardingHelpers)
- Sync CompilerAssert.fs with main (useRawOptions parameter)
- Sync Utilities.fs with main
- Sync project file with main

@T-Gro T-Gro added the NO_RELEASE_NOTES

Label for pull requests which signals, that user opted-out of providing release notes

label

Jan 22, 2026

@T-Gro T-Gro marked this pull request as ready for review

January 22, 2026 09:03

@T-Gro T-Gro changed the title WIP: Goodbye Perl Goodbye Perl

Jan 22, 2026

This was referenced

Jan 28, 2026