diff --git a/test/FsAutoComplete.Tests.Lsp/DecompilerTests.fs b/test/FsAutoComplete.Tests.Lsp/DecompilerTests.fs new file mode 100644 index 000000000..b3ea200d1 --- /dev/null +++ b/test/FsAutoComplete.Tests.Lsp/DecompilerTests.fs @@ -0,0 +1,101 @@ +module FsAutoComplete.Tests.Lsp.DecompilerTests + +open Expecto +open FsAutoComplete.Decompiler +open FSharp.Compiler.Text + +/// Tests for the Decompiler module utility functions +module DecompilerTests = + + /// Tests for file name sanitization + let fileNameSanitizationTests = + testList "File Name Sanitization" [ + + testCase "toSafeFileNameRegex compilation" <| fun _ -> + // Test that the regex compiles and works on basic unsafe characters + let regex = toSafeFileNameRegex + let testInput = "test<>file" + let result = regex.Replace(testInput, "_") + Expect.equal result "test__file" "Should replace unsafe characters with underscores" + + testCase "handles multiple unsafe characters" <| fun _ -> + let regex = toSafeFileNameRegex + let testInput = "test|file:name?" + let result = regex.Replace(testInput, "_") + Expect.equal result "test_file_name_" "Should replace all unsafe characters" + + testCase "leaves safe characters unchanged" <| fun _ -> + let regex = toSafeFileNameRegex + let testInput = "SafeFileName123.cs" + let result = regex.Replace(testInput, "_") + Expect.equal result "SafeFileName123.cs" "Should leave safe characters unchanged" + ] + + /// Tests for type accessibility and compilation + let typeAccessibilityTests = + testList "Type Accessibility Tests" [ + + testCase "DecompileError type is accessible" <| fun _ -> + let decompileErrorType = typeof + Expect.isNotNull decompileErrorType "DecompileError type should be accessible" + + testCase "ExternalContentPosition type is accessible" <| fun _ -> + let externalContentPositionType = typeof + Expect.isNotNull externalContentPositionType "ExternalContentPosition type should be accessible" + + testCase "FindExternalDeclarationError type is accessible" <| fun _ -> + let errorType = typeof + Expect.isNotNull errorType "FindExternalDeclarationError type should be accessible" + ] + + /// Tests for ExternalContentPosition record structure + let externalContentPositionTests = + testList "ExternalContentPosition Tests" [ + + testCase "ExternalContentPosition record construction" <| fun _ -> + let pos = Position.fromZ 10 5 + let position: ExternalContentPosition = { + File = "test.cs" + Position = pos + } + + Expect.equal position.File "test.cs" "Should set file correctly" + Expect.equal position.Position.Line 10 "Should set position line correctly" + Expect.equal position.Position.Column 5 "Should set position column correctly" + + testCase "ExternalContentPosition with empty file" <| fun _ -> + let pos = Position.fromZ 0 0 + let position: ExternalContentPosition = { + File = "" + Position = pos + } + + Expect.equal position.File "" "Should handle empty file name" + Expect.equal position.Position.Line 0 "Should handle zero position" + ] + + /// Tests for module compilation and function accessibility + let moduleAccessibilityTests = + testList "Module Accessibility Tests" [ + + testCase "core functions exist" <| fun _ -> + // Use reflection to verify the function exists and is accessible + let decompilerModule = typeof.DeclaringType + + let decompilerForFileMethod = decompilerModule.GetMethod("decompilerForFile") + Expect.isNotNull decompilerForFileMethod "decompilerForFile function should exist" + + let decompileMethod = decompilerModule.GetMethod("decompile") + Expect.isNotNull decompileMethod "decompile function should exist" + + let tryFindMethod = decompilerModule.GetMethod("tryFindExternalDeclaration") + Expect.isNotNull tryFindMethod "tryFindExternalDeclaration function should exist" + ] + +let tests = + testList "Decompiler Tests" [ + DecompilerTests.fileNameSanitizationTests + DecompilerTests.typeAccessibilityTests + DecompilerTests.externalContentPositionTests + DecompilerTests.moduleAccessibilityTests + ] \ No newline at end of file diff --git a/test/FsAutoComplete.Tests.Lsp/Program.fs b/test/FsAutoComplete.Tests.Lsp/Program.fs index 6736ea79a..65e5e8465 100644 --- a/test/FsAutoComplete.Tests.Lsp/Program.fs +++ b/test/FsAutoComplete.Tests.Lsp/Program.fs @@ -12,6 +12,9 @@ open FsAutoComplete.Tests.ScriptTest open FsAutoComplete.Tests.ExtensionsTests open FsAutoComplete.Tests.InteractiveDirectivesTests open FsAutoComplete.Tests.Lsp.CoreUtilsTests +open FsAutoComplete.Tests.Lsp.SourcelinkTests +open FsAutoComplete.Tests.Lsp.DecompilerTests +open FsAutoComplete.Tests.Lsp.RecordStubGeneratorTests open Ionide.ProjInfo open System.Threading open Serilog.Filters @@ -143,6 +146,9 @@ let lspTests = let generalTests = testList "general" [ testList (nameof (Utils)) [ Utils.Tests.Utils.tests; Utils.Tests.TextEdit.tests ] UtilsTests.allTests + FsAutoComplete.Tests.Lsp.SourcelinkTests.tests + FsAutoComplete.Tests.Lsp.DecompilerTests.tests + FsAutoComplete.Tests.Lsp.RecordStubGeneratorTests.tests InlayHintTests.explicitTypeInfoTests sourceTextFactory FindReferences.tryFixupRangeTests sourceTextFactory ] diff --git a/test/FsAutoComplete.Tests.Lsp/RecordStubGeneratorTests.fs b/test/FsAutoComplete.Tests.Lsp/RecordStubGeneratorTests.fs new file mode 100644 index 000000000..1c8bb32a2 --- /dev/null +++ b/test/FsAutoComplete.Tests.Lsp/RecordStubGeneratorTests.fs @@ -0,0 +1,115 @@ +module FsAutoComplete.Tests.Lsp.RecordStubGeneratorTests + +open Expecto +open FsAutoComplete.RecordStubGenerator +open FSharp.Compiler.Text + +/// Tests for the RecordStubGenerator module +module RecordStubGeneratorTests = + + /// Tests for PositionKind enumeration and basic types + let positionKindTests = + testList "PositionKind Tests" [ + + testCase "PositionKind cases are defined" <| fun _ -> + // Test that all position kind cases are accessible + let _afterLeftBrace = PositionKind.AfterLeftBrace + let _afterCopyExpression = PositionKind.AfterCopyExpression + let _afterLastField = PositionKind.AfterLastField + + Expect.isTrue true "AfterLeftBrace should be defined" + Expect.isTrue true "AfterCopyExpression should be defined" + Expect.isTrue true "AfterLastField should be defined" + + testCase "PositionKind pattern matching works" <| fun _ -> + let testKind = PositionKind.AfterLeftBrace + + let result = + match testKind with + | PositionKind.AfterLeftBrace -> "after brace" + | PositionKind.AfterCopyExpression -> "after copy" + | PositionKind.AfterLastField -> "after field" + + Expect.equal result "after brace" "Pattern matching should work correctly" + ] + + /// Tests for RecordStubsInsertionParams type and construction + let insertionParamsTests = + testList "RecordStubsInsertionParams Tests" [ + + testCase "RecordStubsInsertionParams construction" <| fun _ -> + let pos = Position.fromZ 5 10 + let insertionParams = { + Kind = PositionKind.AfterLeftBrace + InsertionPos = pos + IndentColumn = 4 + } + + Expect.equal insertionParams.Kind PositionKind.AfterLeftBrace "Kind should be set correctly" + Expect.equal insertionParams.InsertionPos.Line 5 "Position line should be set correctly" + Expect.equal insertionParams.InsertionPos.Column 10 "Position column should be set correctly" + Expect.equal insertionParams.IndentColumn 4 "IndentColumn should be set correctly" + ] + + /// Tests for RecordExpr type accessibility + let recordExprTests = + testList "RecordExpr Tests" [ + + testCase "RecordExpr type structure" <| fun _ -> + // Test that we can access the RecordExpr type and its fields + let recordExprType = typeof + Expect.isNotNull recordExprType "RecordExpr type should be accessible" + + // Check that the required fields exist + let exprField = recordExprType.GetProperty("Expr") + let copyExprField = recordExprType.GetProperty("CopyExprOption") + let fieldExprListField = recordExprType.GetProperty("FieldExprList") + let lastKnownPosField = recordExprType.GetProperty("LastKnownGoodPosForSymbolLookup") + + Expect.isNotNull exprField "Expr field should exist" + Expect.isNotNull copyExprField "CopyExprOption field should exist" + Expect.isNotNull fieldExprListField "FieldExprList field should exist" + Expect.isNotNull lastKnownPosField "LastKnownGoodPosForSymbolLookup field should exist" + ] + + /// Tests for module compilation and function accessibility + let moduleAccessibilityTests = + testList "Module Accessibility Tests" [ + + testCase "key functions exist" <| fun _ -> + // Use reflection to verify the function exists and is accessible + let moduleType = typeof.DeclaringType + + let formatRecordMethod = moduleType.GetMethod("formatRecord") + Expect.isNotNull formatRecordMethod "formatRecord function should exist and be accessible" + + let tryFindRecordExprMethod = moduleType.GetMethod("tryFindRecordExprInBufferAtPos") + Expect.isNotNull tryFindRecordExprMethod "tryFindRecordExprInBufferAtPos function should exist" + + let shouldGenerateMethod = moduleType.GetMethod("shouldGenerateRecordStub") + Expect.isNotNull shouldGenerateMethod "shouldGenerateRecordStub function should exist" + ] + + /// Tests for Position integration + let positionTests = + testList "Position Integration Tests" [ + + testCase "Position creation and usage" <| fun _ -> + // Test Position utility functions used in the module + let pos1 = Position.fromZ 10 5 + let pos2 = Position.fromZ 10 5 + let pos3 = Position.fromZ 11 5 + + Expect.equal pos1.Line pos2.Line "Same positions should have same line" + Expect.equal pos1.Column pos2.Column "Same positions should have same column" + Expect.notEqual pos1.Line pos3.Line "Different positions should have different line" + ] + +let tests = + testList "RecordStubGenerator Tests" [ + RecordStubGeneratorTests.positionKindTests + RecordStubGeneratorTests.insertionParamsTests + RecordStubGeneratorTests.recordExprTests + RecordStubGeneratorTests.moduleAccessibilityTests + RecordStubGeneratorTests.positionTests + ] \ No newline at end of file diff --git a/test/FsAutoComplete.Tests.Lsp/SourcelinkTests.fs b/test/FsAutoComplete.Tests.Lsp/SourcelinkTests.fs new file mode 100644 index 000000000..20cc9d8e7 --- /dev/null +++ b/test/FsAutoComplete.Tests.Lsp/SourcelinkTests.fs @@ -0,0 +1,65 @@ +module FsAutoComplete.Tests.Lsp.SourcelinkTests + +open Expecto +open FsAutoComplete.Sourcelink + +/// Tests for the Sourcelink module functions that are accessible +module SourcelinkTests = + + /// Tests for module compilation and basic accessibility + let basicAccessibilityTests = + testList "Basic Accessibility Tests" [ + + testCase "Sourcelink module compiles and is accessible" <| fun _ -> + // Test that the module compiles and key types are accessible + let sourceLinkJsonType = typeof + Expect.isNotNull sourceLinkJsonType "SourceLinkJson type should be accessible" + + testCase "Errors type is accessible" <| fun _ -> + let errorsType = typeof + Expect.isNotNull errorsType "Errors type should be accessible" + + testCase "key functions exist via reflection" <| fun _ -> + // Use reflection to verify key functions exist + let sourceLinkJsonType = typeof + let moduleType = sourceLinkJsonType.DeclaringType + + let tryFetchMethod = moduleType.GetMethod("tryFetchSourcelinkFile") + Expect.isNotNull tryFetchMethod "tryFetchSourcelinkFile function should exist" + ] + + /// Tests for error types + let errorTests = + testList "Error Type Tests" [ + + testCase "Basic error cases are accessible" <| fun _ -> + // Test that basic error cases can be constructed + let _noInfoError = Errors.NoInformation + let _invalidJsonError = Errors.InvalidJson + let _missingSourceError = Errors.MissingSourceFile + let _missingPatternsError = Errors.MissingPatterns + + Expect.isTrue true "NoInformation error should be accessible" + Expect.isTrue true "InvalidJson error should be accessible" + Expect.isTrue true "MissingSourceFile error should be accessible" + Expect.isTrue true "MissingPatterns error should be accessible" + + testCase "Error pattern matching works" <| fun _ -> + let testError error = + match error with + | Errors.NoInformation -> "no-info" + | Errors.InvalidJson -> "invalid-json" + | Errors.MissingSourceFile -> "missing-source" + | Errors.MissingPatterns -> "missing-patterns" + + Expect.equal (testError Errors.NoInformation) "no-info" "NoInformation pattern should match" + Expect.equal (testError Errors.InvalidJson) "invalid-json" "InvalidJson pattern should match" + Expect.equal (testError Errors.MissingSourceFile) "missing-source" "MissingSourceFile pattern should match" + Expect.equal (testError Errors.MissingPatterns) "missing-patterns" "MissingPatterns pattern should match" + ] + +let tests = + testList "Sourcelink Tests" [ + SourcelinkTests.basicAccessibilityTests + SourcelinkTests.errorTests + ] \ No newline at end of file