├── .config └── dotnet-tools.json ├── .gitattributes ├── .github └── workflows │ └── build.yaml ├── .gitignore ├── .paket └── Paket.Restore.targets ├── FSharpApiSearch.sln ├── LICENSE.txt ├── README.md ├── RELEASE_NOTES.md ├── build.fsx ├── paket.dependencies ├── paket.lock ├── src ├── FSharpApiSearch.Console │ ├── App.config │ ├── Args.fs │ ├── AssemblyInfo.fs │ ├── CommandLine.fs │ ├── FSharpApiSearch.Console.fsproj │ ├── Program.fs │ ├── paket.references │ └── paket.template ├── FSharpApiSearch.Database │ ├── App.config │ ├── AssemblyInfo.fs │ ├── FSharpApiSearch.Database.fsproj │ ├── Program.fs │ └── paket.references └── FSharpApiSearch │ ├── AssemblyInfo.fs │ ├── Attributes.fs │ ├── Database │ ├── ApiLoader.fs │ ├── AssemblyLoader.fs │ ├── CompilerOptimization.fs │ ├── ComputationExpressionLoader.fs │ ├── Database.fs │ └── Hack.fs │ ├── Engine │ ├── ContextInitializer.fs │ ├── Engine.fs │ ├── EngineDebug.fs │ ├── EngineStrategy.fs │ ├── EngineTypes.fs │ ├── Matchers │ │ ├── ActivePatternMatcher.fs │ │ ├── CSharpFilter.fs │ │ ├── ComputationExpressionMatcher.fs │ │ ├── ConstraintSolver.fs │ │ ├── LowTypeMatcher.fs │ │ ├── NameMatcher.fs │ │ ├── NameOrSignatureMatcher.fs │ │ ├── NonPublicFilter.fs │ │ ├── SignatureMatcher.fs │ │ ├── TypeHierarchy.fs │ │ └── TypeNameEquality.fs │ └── QueryInitializer.fs │ ├── FSharpApiSearch.fsproj │ ├── FSharpApiSearchClient.fs │ ├── Misc.fs │ ├── Print │ ├── CSharpFormat.fs │ ├── FSharpFormat.fs │ ├── HtmlPrintHelper.fs │ ├── PrintTypes.fs │ ├── Printer.fs │ ├── QueryPrinter.fs │ └── StringPrinter.fs │ ├── QueryParser.fs │ ├── Types.fs │ ├── paket.references │ ├── paket.template │ └── prim-types-members.fsx └── tests ├── CSharpLoadTestAssembly ├── ByRef.cs ├── CSharpLoadTestAssembly.csproj ├── Class.cs ├── Delegate.cs ├── ExtensionMember.cs ├── Interface.cs ├── NestedClass.cs ├── Operators.cs ├── OptinalParameters.cs ├── ParamArray.cs ├── Properties │ └── AssemblyInfo.cs ├── Tuples.cs ├── TypeConstraints.cs └── paket.references ├── FSharpApiSearch.Tests ├── ApiLoaderTest.fs ├── ComputationExpressionMatcherTest.fs ├── DatabaseTest.fs ├── EngineTest.fs ├── FSharpApiSearch.Tests.fsproj ├── FSharpApiSearchClientTest.fs ├── FSharpCompilerServiceTest.fs ├── HtmlPrintHelperTest.fs ├── PrinterTest.fs ├── Program.fs ├── QueryParserTest.fs ├── QueryPrinterTest.fs ├── TestAssemblies.fs ├── TestHelper.fs ├── TypesTest.fs └── paket.references ├── FSharpApiSearch.Trace ├── App.config ├── AssemblyInfo.fs ├── FSharpApiSearch.Trace.fsproj ├── Program.fs └── paket.references ├── LoadTestAssembly ├── AccessPath.fs ├── AssemblyInfo.fs ├── Class.fs ├── CompiledNames.fs ├── ComputationExpression.fs ├── Delegate.fs ├── FSharp41.fs ├── FullTypeDefinition.fs ├── InternalModule.fs ├── InternalSignature.fs ├── InternalSignature.fsi ├── LoadTestAssembly.fsproj ├── Operators.fs ├── OptionalParameters.fs ├── OtherTypes.fs ├── ParamArray.fs ├── PrivateModule.fs ├── PublicModule.fs ├── TypeAbbreviations.fs ├── TypeConstraints.fs ├── TypeExtensions.fs ├── XmlDoc.fs └── paket.references ├── PerformanceTest ├── App.config ├── AssemblyInfo.fs ├── PerformanceTest.fsproj ├── Program.fs └── paket.references ├── Profiling ├── App.config ├── AssemblyInfo.fs ├── Profiling.fsproj ├── Program.fs └── paket.references ├── ProfilingLinkGenerator ├── App.config ├── AssemblyInfo.fs ├── ProfilingLinkGenerator.fsproj ├── Program.fs └── paket.references ├── SearchTestAssembly ├── AssemblyInfo.fs ├── SearchTestAssembly.fsproj ├── TestModule.fs └── paket.references ├── TestApiBrowserLink.fsx ├── TestFParsecLink.fsx ├── TestFSharpLinkExistence.fsx └── TestModuleFSharp.fsx /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "paket": { 6 | "version": "7.1.5", 7 | "commands": [ 8 | "paket" 9 | ] 10 | }, 11 | "fake-cli": { 12 | "version": "5.22.0", 13 | "commands": [ 14 | "fake" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp text=auto eol=lf 6 | *.vb diff=csharp text=auto eol=lf 7 | *.fs diff=csharp text=auto eol=lf 8 | *.fsi diff=csharp text=auto eol=lf 9 | *.fsx diff=csharp text=auto eol=lf 10 | *.sln text eol=crlf merge=union 11 | *.csproj merge=union 12 | *.vbproj merge=union 13 | *.fsproj merge=union 14 | *.dbproj merge=union 15 | 16 | # Standard to msysgit 17 | *.doc diff=astextplain 18 | *.DOC diff=astextplain 19 | *.docx diff=astextplain 20 | *.DOCX diff=astextplain 21 | *.dot diff=astextplain 22 | *.DOT diff=astextplain 23 | *.pdf diff=astextplain 24 | *.PDF diff=astextplain 25 | *.rtf diff=astextplain 26 | *.RTF diff=astextplain 27 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Setup .NET 16 | uses: actions/setup-dotnet@v1 17 | with: 18 | dotnet-version: | 19 | 6.0.x 20 | 21 | - uses: actions/cache@v2 22 | with: 23 | path: ~/.nuget/packages 24 | key: nuget-${{ hashFiles('**/paket.lock') }} 25 | restore-keys: | 26 | nuget-${{ hashFiles('**/paket.lock') }} 27 | nuget 28 | 29 | - name: Restore 30 | run: | 31 | dotnet tool restore 32 | dotnet restore 33 | 34 | - name: Build 35 | run: | 36 | dotnet fake build -t All -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Xamarin Studio / monodevelop user-specific 10 | *.userprefs 11 | *.dll.mdb 12 | *.exe.mdb 13 | 14 | # Build results 15 | 16 | [Dd]ebug/ 17 | [Rr]elease/ 18 | x64/ 19 | build/ 20 | [Bb]in/ 21 | [Oo]bj/ 22 | 23 | # MSTest test Results 24 | [Tt]est[Rr]esult*/ 25 | [Bb]uild[Ll]og.* 26 | 27 | *_i.c 28 | *_p.c 29 | *.ilk 30 | *.meta 31 | *.obj 32 | *.pch 33 | *.pdb 34 | *.pgc 35 | *.pgd 36 | *.rsp 37 | *.sbr 38 | *.tlb 39 | *.tli 40 | *.tlh 41 | *.tmp 42 | *.tmp_proj 43 | *.log 44 | *.vspscc 45 | *.vssscc 46 | .builds 47 | *.pidb 48 | *.log 49 | *.scc 50 | 51 | # Visual C++ cache files 52 | ipch/ 53 | *.aps 54 | *.ncb 55 | *.opensdf 56 | *.sdf 57 | *.cachefile 58 | 59 | # Visual Studio profiler 60 | *.psess 61 | *.vsp 62 | *.vspx 63 | 64 | # Other Visual Studio data 65 | .vs/ 66 | 67 | # Guidance Automation Toolkit 68 | *.gpState 69 | 70 | # ReSharper is a .NET coding add-in 71 | _ReSharper*/ 72 | *.[Rr]e[Ss]harper 73 | 74 | # TeamCity is a build add-in 75 | _TeamCity* 76 | 77 | # DotCover is a Code Coverage Tool 78 | *.dotCover 79 | 80 | # NCrunch 81 | *.ncrunch* 82 | .*crunch*.local.xml 83 | 84 | # Installshield output folder 85 | [Ee]xpress/ 86 | 87 | # DocProject is a documentation generator add-in 88 | DocProject/buildhelp/ 89 | DocProject/Help/*.HxT 90 | DocProject/Help/*.HxC 91 | DocProject/Help/*.hhc 92 | DocProject/Help/*.hhk 93 | DocProject/Help/*.hhp 94 | DocProject/Help/Html2 95 | DocProject/Help/html 96 | 97 | # Click-Once directory 98 | publish/ 99 | 100 | # Publish Web Output 101 | *.Publish.xml 102 | 103 | # Enable nuget.exe in the .nuget folder (though normally executables are not tracked) 104 | !.nuget/NuGet.exe 105 | 106 | # Windows Azure Build Output 107 | csx 108 | *.build.csdef 109 | 110 | # Windows Store app package directory 111 | AppPackages/ 112 | 113 | # Others 114 | sql/ 115 | *.Cache 116 | ClientBin/ 117 | [Ss]tyle[Cc]op.* 118 | ~$* 119 | *~ 120 | *.dbmdl 121 | *.[Pp]ublish.xml 122 | *.pfx 123 | *.publishsettings 124 | 125 | # RIA/Silverlight projects 126 | Generated_Code/ 127 | 128 | # Backup & report files from converting an old project file to a newer 129 | # Visual Studio version. Backup files are not needed, because we have git ;-) 130 | _UpgradeReport_Files/ 131 | Backup*/ 132 | UpgradeLog*.XML 133 | UpgradeLog*.htm 134 | 135 | # SQL Server files 136 | App_Data/*.mdf 137 | App_Data/*.ldf 138 | 139 | 140 | #LightSwitch generated files 141 | GeneratedArtifacts/ 142 | _Pvt_Extensions/ 143 | ModelManifest.xml 144 | 145 | # ========================= 146 | # Windows detritus 147 | # ========================= 148 | 149 | # Windows image file caches 150 | Thumbs.db 151 | ehthumbs.db 152 | 153 | # Folder config file 154 | Desktop.ini 155 | 156 | # Recycle Bin used on file shares 157 | $RECYCLE.BIN/ 158 | 159 | # Mac desktop service store files 160 | .DS_Store 161 | 162 | # =================================================== 163 | # Exclude F# project specific directories and files 164 | # =================================================== 165 | 166 | # NuGet Packages Directory 167 | packages/ 168 | 169 | # Generated documentation folder 170 | docs/output/ 171 | 172 | # Temp folder used for publishing docs 173 | temp/ 174 | 175 | # Test results produced by build 176 | TestResults.xml 177 | 178 | # Nuget outputs 179 | nuget/*.nupkg 180 | release.cmd 181 | release.sh 182 | localpackages/ 183 | paket-files 184 | *.orig 185 | .paket/paket.exe 186 | docs/content/license.md 187 | docs/content/release-notes.md 188 | .fake 189 | docs/tools/FSharp.Formatting.svclog 190 | -------------------------------------------------------------------------------- /FSharpApiSearch.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.1.32421.90 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{63297B98-5CED-492C-A5B7-A5B4F73CF142}" 6 | ProjectSection(SolutionItems) = preProject 7 | paket.dependencies = paket.dependencies 8 | paket.lock = paket.lock 9 | EndProjectSection 10 | EndProject 11 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpApiSearch", "src\FSharpApiSearch\FSharpApiSearch.fsproj", "{DDC5E009-4EFA-49EB-B4AA-46216D00992E}" 12 | EndProject 13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{BF60BC93-E09B-4E5F-9D85-95A519479D54}" 14 | ProjectSection(SolutionItems) = preProject 15 | build.fsx = build.fsx 16 | README.md = README.md 17 | RELEASE_NOTES.md = RELEASE_NOTES.md 18 | EndProjectSection 19 | EndProject 20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{ED8079DD-2B06-4030-9F0F-DC548F98E1C4}" 21 | EndProject 22 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpApiSearch.Tests", "tests\FSharpApiSearch.Tests\FSharpApiSearch.Tests.fsproj", "{88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}" 23 | EndProject 24 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "LoadTestAssembly", "tests\LoadTestAssembly\LoadTestAssembly.fsproj", "{C05F3812-B549-4220-9853-EB4BBBF6C78B}" 25 | EndProject 26 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "SearchTestAssembly", "tests\SearchTestAssembly\SearchTestAssembly.fsproj", "{73F7A955-3F4B-41A0-A522-3C0284B836C6}" 27 | EndProject 28 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpApiSearch.Console", "src\FSharpApiSearch.Console\FSharpApiSearch.Console.fsproj", "{2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}" 29 | EndProject 30 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpApiSearch.Trace", "tests\FSharpApiSearch.Trace\FSharpApiSearch.Trace.fsproj", "{9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpLoadTestAssembly", "tests\CSharpLoadTestAssembly\CSharpLoadTestAssembly.csproj", "{6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}" 33 | EndProject 34 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpApiSearch.Database", "src\FSharpApiSearch.Database\FSharpApiSearch.Database.fsproj", "{161B5314-CBE0-4DF5-A627-72DC0015401D}" 35 | EndProject 36 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "PerformanceTest", "tests\PerformanceTest\PerformanceTest.fsproj", "{3B42A705-701F-4C92-9D32-4A2CE7DE1997}" 37 | EndProject 38 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Profiling", "tests\Profiling\Profiling.fsproj", "{113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}" 39 | EndProject 40 | Global 41 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 42 | Debug|Any CPU = Debug|Any CPU 43 | EngineDebug|Any CPU = EngineDebug|Any CPU 44 | Release|Any CPU = Release|Any CPU 45 | EndGlobalSection 46 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 47 | {DDC5E009-4EFA-49EB-B4AA-46216D00992E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {DDC5E009-4EFA-49EB-B4AA-46216D00992E}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {DDC5E009-4EFA-49EB-B4AA-46216D00992E}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 50 | {DDC5E009-4EFA-49EB-B4AA-46216D00992E}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 51 | {DDC5E009-4EFA-49EB-B4AA-46216D00992E}.Release|Any CPU.ActiveCfg = Release|Any CPU 52 | {DDC5E009-4EFA-49EB-B4AA-46216D00992E}.Release|Any CPU.Build.0 = Release|Any CPU 53 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 56 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 57 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C}.Release|Any CPU.Build.0 = Release|Any CPU 59 | {C05F3812-B549-4220-9853-EB4BBBF6C78B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 60 | {C05F3812-B549-4220-9853-EB4BBBF6C78B}.Debug|Any CPU.Build.0 = Debug|Any CPU 61 | {C05F3812-B549-4220-9853-EB4BBBF6C78B}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 62 | {C05F3812-B549-4220-9853-EB4BBBF6C78B}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 63 | {C05F3812-B549-4220-9853-EB4BBBF6C78B}.Release|Any CPU.ActiveCfg = Release|Any CPU 64 | {C05F3812-B549-4220-9853-EB4BBBF6C78B}.Release|Any CPU.Build.0 = Release|Any CPU 65 | {73F7A955-3F4B-41A0-A522-3C0284B836C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 66 | {73F7A955-3F4B-41A0-A522-3C0284B836C6}.Debug|Any CPU.Build.0 = Debug|Any CPU 67 | {73F7A955-3F4B-41A0-A522-3C0284B836C6}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 68 | {73F7A955-3F4B-41A0-A522-3C0284B836C6}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 69 | {73F7A955-3F4B-41A0-A522-3C0284B836C6}.Release|Any CPU.ActiveCfg = Release|Any CPU 70 | {73F7A955-3F4B-41A0-A522-3C0284B836C6}.Release|Any CPU.Build.0 = Release|Any CPU 71 | {2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 72 | {2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}.Debug|Any CPU.Build.0 = Debug|Any CPU 73 | {2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 74 | {2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 75 | {2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}.Release|Any CPU.ActiveCfg = Release|Any CPU 76 | {2C2F8D38-E62F-41CD-A4CC-DC5C74DF3B08}.Release|Any CPU.Build.0 = Release|Any CPU 77 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 78 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}.Debug|Any CPU.Build.0 = Debug|Any CPU 79 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 80 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 81 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}.Release|Any CPU.ActiveCfg = Release|Any CPU 82 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9}.Release|Any CPU.Build.0 = Release|Any CPU 83 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 84 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}.Debug|Any CPU.Build.0 = Debug|Any CPU 85 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 86 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 87 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}.Release|Any CPU.ActiveCfg = Release|Any CPU 88 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62}.Release|Any CPU.Build.0 = Release|Any CPU 89 | {161B5314-CBE0-4DF5-A627-72DC0015401D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 90 | {161B5314-CBE0-4DF5-A627-72DC0015401D}.Debug|Any CPU.Build.0 = Debug|Any CPU 91 | {161B5314-CBE0-4DF5-A627-72DC0015401D}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 92 | {161B5314-CBE0-4DF5-A627-72DC0015401D}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 93 | {161B5314-CBE0-4DF5-A627-72DC0015401D}.Release|Any CPU.ActiveCfg = Release|Any CPU 94 | {161B5314-CBE0-4DF5-A627-72DC0015401D}.Release|Any CPU.Build.0 = Release|Any CPU 95 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 96 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997}.Debug|Any CPU.Build.0 = Debug|Any CPU 97 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 98 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 99 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997}.Release|Any CPU.ActiveCfg = Release|Any CPU 100 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997}.Release|Any CPU.Build.0 = Release|Any CPU 101 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 102 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}.Debug|Any CPU.Build.0 = Debug|Any CPU 103 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}.EngineDebug|Any CPU.ActiveCfg = EngineDebug|Any CPU 104 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}.EngineDebug|Any CPU.Build.0 = EngineDebug|Any CPU 105 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}.Release|Any CPU.ActiveCfg = Release|Any CPU 106 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72}.Release|Any CPU.Build.0 = Release|Any CPU 107 | EndGlobalSection 108 | GlobalSection(SolutionProperties) = preSolution 109 | HideSolutionNode = FALSE 110 | EndGlobalSection 111 | GlobalSection(NestedProjects) = preSolution 112 | {88A38F77-760F-4E3A-8A2D-7BC80B7C5A8C} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 113 | {C05F3812-B549-4220-9853-EB4BBBF6C78B} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 114 | {73F7A955-3F4B-41A0-A522-3C0284B836C6} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 115 | {9B49EA5B-EF46-44D5-ABDE-58E092F72FA9} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 116 | {6273542C-01F5-4EBF-8AAB-9FCAA96BEA62} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 117 | {3B42A705-701F-4C92-9D32-4A2CE7DE1997} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 118 | {113D6BCE-EC7F-46B0-B4FD-58C2C9AFFB72} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} 119 | EndGlobalSection 120 | GlobalSection(ExtensibilityGlobals) = postSolution 121 | SolutionGuid = {5C4524B2-F097-4B90-8DC3-33CE73C535B1} 122 | EndGlobalSection 123 | EndGlobal 124 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 MIYAZAKI Shohei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | ### 4.1.0 - Unreleased 2 | * Load implicit assemblies automatically 3 | * Improve database size 4 | 5 | ### 4.0.1 6 | * Fix to allow substring matching in name search 7 | * Improve sort order 8 | * Improve performance 9 | 10 | ### 4.0.0 11 | * Add type coloring 12 | * Add substring matching and `--substring` option 13 | * Allow `_` for wildcard 14 | * Fix type variable bug (#139) 15 | * Improve performance 16 | 17 | ### 4.0.0-beta1 18 | * Add type coloring 19 | * Fix type variable bug (#139) 20 | * Improve performance 21 | 22 | ### 3.0.4 23 | * Fix print bugs (generic method and generic type abbreviation) 24 | 25 | ### 3.0.3 26 | * Ignore the invalid xml 27 | 28 | ### 3.0.2 29 | * Fix the link generator of .Net Api Browser 30 | 31 | ### 3.0.1 32 | * Fix the link generator of .Net Api Browser 33 | 34 | ### 3.0.0 35 | * Add subtype matching 36 | * Add name search by single type query 37 | * Add C# mode (experimental) and `--language` option 38 | * Support struct tuple 39 | * Add `--single-letter-as-variable` option 40 | * Add the link generator to .Net Api Browser 41 | * Add the link generator to the reference of FParsec 42 | * Remove `=>` syntax 43 | * Change serialization library to MessagePack from FsPickler 44 | 45 | ### 3.0.0-beta4 46 | * Fix bugs 47 | * Improve performance 48 | * Change seliarization library to MessagePack from FsPickler 49 | 50 | ### 3.0.0-beta3 51 | * Add flexible type matching 52 | * Improve results display 53 | * Fix C# parser 54 | 55 | ### 3.0.0-beta2 56 | * Change byref matching 57 | * Change the result format 58 | * Add the link generator to .Net Api Browser 59 | 60 | ### 3.0.0-beta1 61 | * Support struct tuple 62 | * Remove `=>` syntax 63 | * Add C# mode 64 | 65 | ### 2.1.2 - 2017/1/26 66 | * Fix the computation expression builder url 67 | 68 | ### 2.1.1 - 2016/12/29 69 | * Fix the distance of swap-order 70 | 71 | ### 2.1.0 - 2016/12/6 72 | * Support computation expression 73 | * Add swapping parameters and tuple elements 74 | * Add complementing parameters and tuple elements 75 | * Fix type abbreviation result 76 | * Fix automatic generalization parameter 77 | * Improve assembly loading 78 | 79 | ### 2.0.0 - 2016/10/20 80 | Engine 81 | * Improve the display of the parameter name 82 | * Support optional parameters 83 | * Add `--ignore-case` option 84 | * Add type and type abbreviation searching 85 | * Add module searching 86 | * Add union case searching 87 | * Add convertion between function and delegate 88 | * Change the constructor name query to "T.new : _", "T..ctor : _" and "T : _" from "T : _" 89 | * Add partial matching to name searching 90 | 91 | Libarary 92 | * Add FSharpApiSearch.LinkGenerator module 93 | * Change SearchOption's accessors to function 94 | 95 | Console 96 | * Add `#clear` command to clear the console buffer 97 | * Add `#targets` command to list target assemblies 98 | * Improve the startup time 99 | 100 | ### 2.0.0-beta2 - 2016/10/13 101 | Engine 102 | * Add partial matching to name searching 103 | * Add module searching 104 | * Add the namespace to the result of type abbreviation 105 | * Change to allow the type name and ".ctor" to the constructor 106 | * Improve type abbreviation matching with the ignore-case option 107 | * Fix to ignore private type definition 108 | 109 | Console 110 | * Add `#clear` command to clear the console buffer 111 | * Improve the startup time 112 | 113 | ### 2.0.0-beta1 - 2016/9/29 114 | Engine 115 | * Improve the display of the parameter name 116 | * Add `--ignore-case` option 117 | * Add type and type abbreviation searching 118 | * Add conversion between function and delegate 119 | * Support union case 120 | * Support optional parameters 121 | * Change the constructor name query to "new : _" 122 | 123 | Library 124 | * Add LinkGenerator module 125 | * Change the SearchOptions's accessor to function 126 | 127 | ### 1.0.1 - 2016/9/26 128 | * Allow digit, _ and ' in the name search query (#92) 129 | 130 | ### 1.0.0 - 2016/7/29 131 | * Add the assembly name to the result 132 | * Add the namespace searching (#9) 133 | * Change the search option names (#61) 134 | 135 | ### 0.4.0-beta - 2016/6/23 136 | * Change the first argument to search as a receiver (#80) 137 | * Add searching by operator name 138 | * Add `--xmldoc` option to show xml document 139 | * Fix loading bugs (#41, #83) 140 | * Fix searching bugs (#78, #68) 141 | 142 | ### 0.3.1-beta - 2016/6/14 143 | * Fix error at similarity searching (#81) 144 | 145 | ### 0.3.0-beta - 2016/5/22 146 | * Support active pattern 147 | * Support function type abbreviation 148 | * Support type extension and extension member 149 | * Fix array printing (#57) 150 | 151 | ### 0.2.1-beta - 2016/5/15 152 | * Fix loading type constraints of type abbreviation (#66) 153 | * Fix FSharpApiSearch.Database.exe option's bugs (#65, #67) 154 | 155 | ### 0.2.0-beta - 2016/4/27 156 | * Support type constraints at similarity searching 157 | * Exclude the modules (LanguagePrimitives and OperatorIntrinsics) for the F# compiler 158 | * Add ignore-argstyle option 159 | * Improve the start-up time by database 160 | 161 | ### 0.1.0-beta 162 | * Initial release 163 | -------------------------------------------------------------------------------- /build.fsx: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------- 2 | // FAKE build script 3 | // -------------------------------------------------------------------------------------- 4 | 5 | #r "paket: groupref Build //" 6 | #load ".fake/build.fsx/intellisense.fsx" 7 | 8 | open Fake.Api 9 | open Fake.Core 10 | open Fake.Core.TargetOperators 11 | open Fake.DotNet 12 | open Fake.IO 13 | open Fake.IO.FileSystemOperators 14 | open Fake.IO.Globbing.Operators 15 | open Fake.Tools.Git 16 | open System.IO 17 | 18 | Target.initEnvironment () 19 | 20 | // The name of the project 21 | // (used by attributes in AssemblyInfo, name of a NuGet package and directory in 'src') 22 | let project = "FSharpApiSearch" 23 | 24 | // Longer description of the project 25 | // (used as a description for NuGet package; line breaks are automatically cleaned up) 26 | let description = "F# API search engine" 27 | 28 | // Default target configuration 29 | let configuration = Environment.environVarOrDefault "configuration" "Release" 30 | 31 | // Pattern specifying assemblies to be tested using Persimmon 32 | let testAssemblies = "tests/**/bin" configuration "*" "*.Tests.exe" 33 | 34 | // Git configuration (used for publishing documentation in gh-pages branch) 35 | // The profile where the project is posted 36 | let gitOwner = "hafuu" 37 | let gitHome = sprintf "%s/%s" "https://github.com" gitOwner 38 | 39 | // The name of the project on GitHub 40 | let gitName = "FSharpApiSearch" 41 | 42 | // The url for the raw files hosted 43 | let gitRaw = Environment.environVarOrDefault "gitRaw" "https://raw.githubusercontent.com/hafuu" 44 | 45 | let outDir = "bin" 46 | 47 | // -------------------------------------------------------------------------------------- 48 | // END TODO: The rest of the file includes standard build steps 49 | // -------------------------------------------------------------------------------------- 50 | 51 | // Read additional information from the release notes document 52 | let release = ReleaseNotes.load "RELEASE_NOTES.md" 53 | 54 | // Helper active pattern for project types 55 | let (|Fsproj|Csproj|Vbproj|Shproj|) (projFileName:string) = 56 | match projFileName with 57 | | f when f.EndsWith("fsproj") -> Fsproj 58 | | f when f.EndsWith("csproj") -> Csproj 59 | | f when f.EndsWith("vbproj") -> Vbproj 60 | | f when f.EndsWith("shproj") -> Shproj 61 | | _ -> failwith (sprintf "Project file %s not supported. Unknown project type." projFileName) 62 | 63 | // Generate assembly info files with the right version & up-to-date information 64 | Target.create "AssemblyInfo" (fun _ -> 65 | let getAssemblyInfoAttributes projectName = 66 | [ AssemblyInfo.Title projectName 67 | AssemblyInfo.Product project 68 | AssemblyInfo.Description description 69 | AssemblyInfo.Version release.AssemblyVersion 70 | AssemblyInfo.FileVersion release.AssemblyVersion 71 | AssemblyInfo.Configuration configuration ] 72 | 73 | let getProjectDetails (projectPath: string) = 74 | let projectName = System.IO.Path.GetFileNameWithoutExtension(projectPath) 75 | ( projectPath, 76 | projectName, 77 | System.IO.Path.GetDirectoryName(projectPath), 78 | (getAssemblyInfoAttributes projectName) 79 | ) 80 | 81 | !! "src/**/*.??proj" 82 | |> Seq.map getProjectDetails 83 | |> Seq.iter (fun (projFileName, _, folderName, attributes) -> 84 | match projFileName with 85 | | Fsproj -> AssemblyInfoFile.createFSharp (folderName "AssemblyInfo.fs") attributes 86 | | Csproj -> AssemblyInfoFile.createCSharp (folderName "Properties" "AssemblyInfo.cs") attributes 87 | | Vbproj -> AssemblyInfoFile.createVisualBasic (folderName "My Project" "AssemblyInfo.vb") attributes 88 | | Shproj -> () 89 | ) 90 | ) 91 | 92 | // Copies binaries from default VS location to expected bin folder 93 | // But keeps a subdirectory structure for each project in the 94 | // src folder to support multiple project outputs 95 | Target.create "CopyBinaries" (fun _ -> 96 | !! "src/**/*.??proj" 97 | |> Seq.map (fun f -> ((System.IO.Path.GetDirectoryName f) @@ "bin" @@ configuration, outDir @@ (System.IO.Path.GetFileNameWithoutExtension f))) 98 | |> Seq.iter (fun (fromDir, toDir) -> Shell.copyDir toDir fromDir (fun _ -> true)) 99 | ) 100 | 101 | // -------------------------------------------------------------------------------------- 102 | // Clean build results 103 | 104 | 105 | Target.create "Clean" (fun _ -> 106 | !! "**/bin" 107 | ++ "**/obj" 108 | ++ outDir 109 | |> Shell.cleanDirs 110 | ) 111 | 112 | // -------------------------------------------------------------------------------------- 113 | // Build library & test project 114 | 115 | Target.create "Build" (fun _ -> 116 | !! "*.sln" 117 | |> Seq.iter (DotNet.build (fun args -> 118 | { args with 119 | Configuration = DotNet.BuildConfiguration.fromString configuration 120 | })) 121 | ) 122 | 123 | // -------------------------------------------------------------------------------------- 124 | // Run the unit tests using test runner 125 | 126 | Target.create "RunTests" (fun _ -> 127 | let result = 128 | !! testAssemblies 129 | |> Seq.map (fun testAsm -> 130 | Command.RawCommand(testAsm, Arguments.Empty) 131 | |> CreateProcess.fromCommand 132 | |> Proc.run 133 | ) 134 | |> Seq.sumBy (fun result -> result.ExitCode) 135 | if result <> 0 then failwith "Some tests failed." 136 | ) 137 | 138 | // -------------------------------------------------------------------------------------- 139 | // Build a NuGet package 140 | 141 | Target.create "NuGet" (fun _ -> 142 | use trace = Trace.traceTask "PaketPack" "." 143 | let args = 144 | Arguments.OfArgs([ "pack" ]) 145 | |> Arguments.append [ "--version"; release.NugetVersion ] 146 | |> Arguments.append [ "--release-notes"; System.Net.WebUtility.HtmlEncode(release.Notes |> String.concat System.Environment.NewLine) ] 147 | |> Arguments.append [ outDir ] 148 | let result = DotNet.exec id "paket" (args.ToWindowsCommandLine) 149 | if not result.OK then failwith "Error during packing." 150 | trace.MarkSuccess() 151 | ) 152 | 153 | Target.create "PublishNuget" (fun _ -> 154 | let apiKey = Environment.environVar "api-key" 155 | if (String.isNullOrEmpty apiKey = false) then TraceSecrets.register "" apiKey 156 | 157 | !! (outDir @@ "/**/*.nupkg") 158 | |> Seq.iter (fun package -> 159 | use trace = Trace.traceTask "PaketPublish" package 160 | let args = 161 | Arguments.OfArgs([ "push" ]) 162 | |> Arguments.appendNotEmpty "--api-key" apiKey 163 | |> Arguments.append([ package ]) 164 | let result = DotNet.exec id "paket" (args.ToWindowsCommandLine) 165 | if not result.OK then failwithf "Error during pushing %s" package 166 | trace.MarkSuccess() 167 | ) 168 | ) 169 | 170 | // -------------------------------------------------------------------------------------- 171 | // Build a zip package 172 | 173 | let githubReleaseFilePath = outDir @@ (project + ".zip") 174 | 175 | Target.create "PackGithubRelease" (fun _ -> 176 | [ "FSharpApiSearch.Console"; "FSharpApiSearch.Database" ] 177 | |> Seq.map (fun proj -> 178 | let projDir = outDir proj 179 | !! (projDir @@ "*" @@ "*.dll") 180 | ++ (projDir @@ "*" @@ "*.exe") 181 | ++ (projDir @@ "*" @@ "*.config") 182 | ++ (projDir @@ "*" @@ "*.json") 183 | |> Zip.filesAsSpecsFlatten 184 | |> Zip.moveToFolder project 185 | ) 186 | |> Seq.concat 187 | |> Seq.distinctBy(fun (f, _) -> Path.GetFileName(f)) 188 | |> Zip.zipSpec githubReleaseFilePath 189 | ) 190 | 191 | // -------------------------------------------------------------------------------------- 192 | // Release Scripts 193 | 194 | Target.create "Release" (fun _ -> 195 | Staging.stageAll "" 196 | Commit.exec "" (sprintf "Bump version to %s" release.NugetVersion) 197 | Branches.pushBranch "" "origin" "master" 198 | 199 | Branches.tag "" release.NugetVersion 200 | Branches.pushTag "" "origin" release.NugetVersion 201 | 202 | 203 | //// release on github 204 | //let user = Environment.environVar "github-user" 205 | //if String.isNullOrEmpty user then TraceSecrets.register "" user 206 | //let password = Environment.environVar "github-pw" 207 | //if String.isNotNullOrEmpty password then TraceSecrets.register "" password 208 | //GitHub.createClient user password 209 | //|> GitHub.draftNewRelease gitOwner gitName release.NugetVersion (release.SemVer.PreRelease <> None) release.Notes 210 | //// TODO: |> uploadFile "PATH_TO_FILE" 211 | //|> GitHub.publishDraft 212 | //|> Async.RunSynchronously 213 | ) 214 | 215 | // -------------------------------------------------------------------------------------- 216 | // Run all targets by default. Invoke 'build ' to override 217 | 218 | Target.create "All" ignore 219 | 220 | "Clean" 221 | ==> "AssemblyInfo" 222 | ==> "Build" 223 | ==> "CopyBinaries" 224 | ==> "RunTests" 225 | ==> "NuGet" 226 | ==> "PackGithubRelease" 227 | ==> "All" 228 | 229 | Target.runOrDefault "All" -------------------------------------------------------------------------------- /paket.dependencies: -------------------------------------------------------------------------------- 1 | group Core 2 | framework: netstandard2.0 3 | source https://api.nuget.org/v3/index.json 4 | storage: none 5 | 6 | nuget FSharp.Core 7 | nuget FParsec 8 | nuget FSharp.Compiler.Service = 41.0.2 9 | nuget FSharp.Collections.ParallelSeq 10 | nuget MessagePack 11 | nuget MessagePack.FSharpExtensions 12 | nuget System.Reflection.Metadata 13 | 14 | 15 | group App 16 | framework: net60 17 | source https://api.nuget.org/v3/index.json 18 | storage: none 19 | 20 | nuget FSharp.Core 21 | nuget FParsec 22 | nuget FSharp.Compiler.Service = 41.0.2 23 | nuget FSharp.Collections.ParallelSeq 24 | nuget MessagePack 25 | nuget MessagePack.FSharpExtensions 26 | nuget System.Reflection.Metadata 27 | nuget System.ValueTuple 28 | 29 | nuget BenchmarkDotNet 30 | 31 | nuget Persimmon 32 | nuget Persimmon.Runner 33 | nuget Persimmon.MuscleAssert 34 | 35 | group Build 36 | framework: net60 37 | source https://api.nuget.org/v3/index.json 38 | storage: none 39 | 40 | nuget Fake.Api.GitHub 41 | nuget Fake.Core.Process 42 | nuget Fake.Core.ReleaseNotes 43 | nuget Fake.Core.String 44 | nuget Fake.Core.Target 45 | nuget Fake.Core.Trace 46 | nuget Fake.DotNet.AssemblyInfoFile 47 | nuget Fake.DotNet.Cli 48 | nuget Fake.IO.FileSystem 49 | nuget Fake.IO.Zip 50 | nuget Fake.Tools.Git 51 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/Args.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch.Console 2 | 3 | open FSharpApiSearch 4 | open System.Diagnostics 5 | open System 6 | 7 | type Args = { 8 | Query: string option 9 | Targets: string list 10 | SearchOptions: SearchOptions 11 | ShowXmlDocument: OptionStatus 12 | ShowDistance: OptionStatus 13 | StackTrace: OptionStatus 14 | Help: bool 15 | } 16 | 17 | module Args = 18 | open FSharpApiSearch.CommandLine 19 | 20 | let empty = 21 | let defaultOpt = SearchOptions.defaultOptions |> SearchOptions.Parallel.Set Enabled 22 | { Query = None; Targets = []; SearchOptions = defaultOpt; ShowXmlDocument = Disabled; ShowDistance = Disabled; StackTrace = Disabled; Help = false } 23 | 24 | let boolToOptionStatus = function true -> Enabled | false -> Disabled 25 | 26 | let rec parse arg = function 27 | | Status "--respect-name-difference" v :: rest -> parse { arg with SearchOptions = SearchOptions.RespectNameDifference.Set (boolToOptionStatus v) arg.SearchOptions } rest 28 | | Status "--greedy-matching" v :: rest -> parse { arg with SearchOptions = SearchOptions.GreedyMatching.Set (boolToOptionStatus v) arg.SearchOptions } rest 29 | | Status "--ignore-param-style" v :: rest -> parse { arg with SearchOptions = SearchOptions.IgnoreParameterStyle.Set (boolToOptionStatus v) arg.SearchOptions } rest 30 | | Status "--ignore-case" v :: rest -> parse { arg with SearchOptions = SearchOptions.IgnoreCase.Set (boolToOptionStatus v) arg.SearchOptions } rest 31 | | Status "--substring" v :: rest -> parse { arg with SearchOptions = SearchOptions.Substring.Set (boolToOptionStatus v) arg.SearchOptions } rest 32 | | Status "--swap-order" v :: rest -> parse { arg with SearchOptions = SearchOptions.SwapOrder.Set (boolToOptionStatus v) arg.SearchOptions } rest 33 | | Status "--complement" v :: rest -> parse { arg with SearchOptions = SearchOptions.Complement.Set (boolToOptionStatus v) arg.SearchOptions } rest 34 | | Status "--single-letter-as-variable" v :: rest -> parse { arg with SearchOptions = SearchOptions.SingleLetterAsVariable.Set (boolToOptionStatus v) arg.SearchOptions } rest 35 | | Language "--language" lang :: rest -> parse { arg with SearchOptions = SearchOptions.Language.Set lang arg.SearchOptions } rest 36 | | (KeyValue "--target" t | KeyValue "-t" t) :: rest -> parse { arg with Targets = t :: arg.Targets } rest 37 | | Status "--xmldoc" v :: rest -> parse { arg with ShowXmlDocument = boolToOptionStatus v } rest 38 | | Status "--distance" v :: rest -> parse { arg with ShowDistance = boolToOptionStatus v } rest 39 | | Status "--stacktrace" v :: rest -> parse { arg with StackTrace = boolToOptionStatus v } rest 40 | | ("--help" | "-h") :: rest -> parse { arg with Help = true } rest 41 | | query :: rest -> 42 | let q = 43 | match arg.Query with 44 | | None -> Some query 45 | | Some _ as q -> q 46 | parse { arg with Query = q } rest 47 | | [] -> arg 48 | 49 | let targetsOrDefault arg = 50 | if List.isEmpty arg.Targets then 51 | FSharpApiSearchClient.DefaultTargets 52 | else 53 | arg.Targets -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | // Auto-Generated by FAKE; do not edit 2 | namespace System 3 | open System.Reflection 4 | 5 | [] 6 | [] 7 | [] 8 | [] 9 | [] 10 | [] 11 | do () 12 | 13 | module internal AssemblyVersionInformation = 14 | let [] AssemblyTitle = "FSharpApiSearch.Console" 15 | let [] AssemblyProduct = "FSharpApiSearch" 16 | let [] AssemblyDescription = "F# API search engine" 17 | let [] AssemblyVersion = "4.1.0" 18 | let [] AssemblyFileVersion = "4.1.0" 19 | let [] AssemblyConfiguration = "Release" 20 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/CommandLine.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.CommandLine 2 | 3 | let (|Status|_|) (name: string) (str: string) = 4 | if str.StartsWith(name) then 5 | match str.Substring(name.Length) with 6 | | "+" -> Some true 7 | | "-" -> Some false 8 | | _ -> None 9 | else 10 | None 11 | 12 | let (|Number|_|) (str: string) = 13 | match System.Int32.TryParse(str) with 14 | | true, x -> Some x 15 | | false, _ -> None 16 | 17 | let (|KeyValue|_|) key (str: string) = 18 | match str.Split([| ':' |], 2) |> Array.toList with 19 | | [ k; v ] when key = k -> Some v 20 | | _ -> None 21 | 22 | let (|Language|_|) key (str: string) = 23 | match str.Split([| ':' |], 2) |> Array.toList with 24 | | [ k; v ] when key = k -> Language.tryParse v 25 | | _ -> None -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/FSharpApiSearch.Console.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | FSharpApiSearch.Console 8 | true 9 | 3 10 | false 11 | 12 | 13 | portable 14 | false 15 | 16 | 17 | portable 18 | true 19 | 20 | 21 | true 22 | portable 23 | false 24 | false 25 | DEBUG;TRACE 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FParsec 4 | FSharp.Compiler.Service 5 | FSharp.Collections.ParallelSeq 6 | MessagePack 7 | MessagePack.FSharpExtensions -------------------------------------------------------------------------------- /src/FSharpApiSearch.Console/paket.template: -------------------------------------------------------------------------------- 1 | type file 2 | id FSharpApiSearch.Console 3 | owners 4 | hafuu 5 | authors 6 | hafuu 7 | projectUrl 8 | http://github.com/hafuu/FSharpApiSearch 9 | licenseUrl 10 | http://github.com/hafuu/FSharpApiSearch/blob/master/LICENSE.txt 11 | requireLicenseAcceptance 12 | false 13 | tags 14 | F# fsharp api search 15 | summary 16 | The console of FSharpApiSearch. 17 | description 18 | The console of FSharpApiSearch. 19 | files 20 | ../../bin/FSharpApiSearch.Database/*/*.dll ==> tools 21 | ../../bin/FSharpApiSearch.Database/*/*.exe ==> tools 22 | ../../bin/FSharpApiSearch.Database/*/*.config ==> tools 23 | ../../bin/FSharpApiSearch.Database/*/*.json ==> tools 24 | ../../bin/FSharpApiSearch.Console/*/*.dll ==> tools 25 | ../../bin/FSharpApiSearch.Console/*/*.exe ==> tools 26 | ../../bin/FSharpApiSearch.Console/*/*.config ==> tools 27 | ../../bin/FSharpApiSearch.Console/*/*.json ==> tools 28 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Database/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Database/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | // Auto-Generated by FAKE; do not edit 2 | namespace System 3 | open System.Reflection 4 | 5 | [] 6 | [] 7 | [] 8 | [] 9 | [] 10 | [] 11 | do () 12 | 13 | module internal AssemblyVersionInformation = 14 | let [] AssemblyTitle = "FSharpApiSearch.Database" 15 | let [] AssemblyProduct = "FSharpApiSearch" 16 | let [] AssemblyDescription = "F# API search engine" 17 | let [] AssemblyVersion = "4.1.0" 18 | let [] AssemblyFileVersion = "4.1.0" 19 | let [] AssemblyConfiguration = "Release" 20 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Database/FSharpApiSearch.Database.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | FSharpApiSearch.Database 8 | 3 9 | true 10 | false 11 | 12 | 13 | portable 14 | false 15 | 16 | 17 | portable 18 | true 19 | 20 | 21 | true 22 | portable 23 | false 24 | false 25 | DEBUG;TRACE 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/FSharpApiSearch.Database/Program.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.Database.Program 2 | 3 | open FSharpApiSearch 4 | open CommandLine 5 | open System.IO 6 | open System.Reflection 7 | open System 8 | 9 | type Args = { 10 | AssemblyResolver : AssemblyLoader.AssemblyResolver 11 | References: string list 12 | Help: bool 13 | } 14 | 15 | module Args = 16 | let defaultArg = { 17 | AssemblyResolver = 18 | { 19 | FSharpCore = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 20 | Framework = 21 | [ 22 | Path.Combine( 23 | System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) 24 | , @"dotnet\shared\Microsoft.NETCore.App\" 25 | , string System.Environment.Version) 26 | ] 27 | Directories = [] 28 | } 29 | References = [] 30 | Help = false 31 | } 32 | 33 | let rec parse arg = function 34 | | KeyValue "--FSharpCore" path :: rest -> parse { arg with AssemblyResolver = { arg.AssemblyResolver with FSharpCore = path } } rest 35 | | KeyValue "--Framework" path :: rest -> parse { arg with AssemblyResolver = { arg.AssemblyResolver with Framework = path :: arg.AssemblyResolver.Framework } } rest 36 | | KeyValue "--lib" path :: rest -> parse { arg with AssemblyResolver = { arg.AssemblyResolver with Directories = path :: arg.AssemblyResolver.Directories } } rest 37 | | ("--help" | "-h") :: rest -> parse { arg with Help = true } rest 38 | | path :: rest -> parse { arg with References = path :: arg.References } rest 39 | | [] -> arg 40 | 41 | let helpMessage = """usage: FSharpApiSearch.Database.exe 42 | 43 | assemblies: Specifies the assembly name or the assembly path. 44 | By default, 'mscorlib', 'System', 'System.Core' and 'FSharp.Core' are specified. 45 | options: 46 | --lib: 47 | Specifies a directory to be searched for assemblies that are referenced. 48 | --FSharpCore: 49 | Specifies the FSharp.Core path. 50 | If omitted, it will use the value in 'FSharpApiSearch.Database.exe.config'. 51 | --Framework: 52 | Specifies a directory to be searched for .Net Framework assemblies that are references. 53 | If omitted, it will use the value in 'FSharpApiSearch.Database.exe.config'. 54 | --help, -h 55 | Print this message.""" 56 | 57 | let printAssemblies (assemblies: AssemblyLoader.AssemblyInfo[]) = 58 | printfn "Create the database of the following assemblies." 59 | assemblies 60 | |> Array.iter (fun a -> printfn " %s" a.Path) 61 | 62 | let printForwardingLogs (apiDict: ApiDictionary, logs: seq) = 63 | if Seq.isEmpty logs then 64 | () 65 | else 66 | printfn "%s type forwarding" apiDict.AssemblyName 67 | logs 68 | |> Seq.sortBy (fun tf -> tf.Type) 69 | |> Seq.iter (fun tf -> 70 | printfn " %s : %s -> %s" tf.Type tf.From tf.To 71 | ) 72 | 73 | let printApiNumber (dictionaries: ApiDictionary[]) = 74 | printfn "Finished." 75 | dictionaries 76 | |> Array.iter (fun apiDic -> 77 | printfn " %s : %d" apiDic.AssemblyName apiDic.PublicApiNumber 78 | ) 79 | 80 | [] 81 | let main argv = 82 | let args = Args.parse Args.defaultArg (List.ofArray argv) 83 | match args with 84 | | { Help = true } -> 85 | printfn "%s" helpMessage 86 | 0 87 | | _ -> 88 | try 89 | let assemblies = 90 | match args.References with 91 | | [] -> FSharpApiSearchClient.DefaultTargets 92 | | _ -> List.rev args.References 93 | let assemblies = args.AssemblyResolver.ResolveAll(assemblies) 94 | printAssemblies assemblies 95 | let databaseResult = 96 | AssemblyLoader.load assemblies 97 | |> ApiLoader.loadWithLogs 98 | 99 | databaseResult |> Array.iter printForwardingLogs 100 | 101 | let database = 102 | databaseResult 103 | |> Array.map fst 104 | |> Database.compact assemblies 105 | 106 | printApiNumber database 107 | 108 | printfn "Saving database." 109 | Database.save Database.databaseName database 110 | 0 111 | with ex -> 112 | printfn "%A" ex 113 | 1 -------------------------------------------------------------------------------- /src/FSharpApiSearch.Database/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FParsec 4 | FSharp.Compiler.Service 5 | FSharp.Collections.ParallelSeq 6 | MessagePack 7 | MessagePack.FSharpExtensions -------------------------------------------------------------------------------- /src/FSharpApiSearch/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | // Auto-Generated by FAKE; do not edit 2 | namespace System 3 | open System.Reflection 4 | 5 | [] 6 | [] 7 | [] 8 | [] 9 | [] 10 | [] 11 | do () 12 | 13 | module internal AssemblyVersionInformation = 14 | let [] AssemblyTitle = "FSharpApiSearch" 15 | let [] AssemblyProduct = "FSharpApiSearch" 16 | let [] AssemblyDescription = "F# API search engine" 17 | let [] AssemblyVersion = "4.1.0" 18 | let [] AssemblyFileVersion = "4.1.0" 19 | let [] AssemblyConfiguration = "Release" 20 | -------------------------------------------------------------------------------- /src/FSharpApiSearch/Attributes.fs: -------------------------------------------------------------------------------- 1 | namespace System 2 | open System.Runtime.CompilerServices 3 | 4 | [] 5 | do () -------------------------------------------------------------------------------- /src/FSharpApiSearch/Database/AssemblyLoader.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.AssemblyLoader 2 | 3 | open FSharp.Compiler.CodeAnalysis 4 | open System.IO 5 | open System.Reflection 6 | open System.Collections.Generic 7 | open System.Reflection.Metadata 8 | open System.Reflection.PortableExecutable 9 | 10 | type AssemblyInfo = { 11 | Name: string 12 | Path: string 13 | Implicit: bool 14 | } 15 | 16 | type AssemblyResolver = { 17 | FSharpCore: string 18 | Framework: string list 19 | Directories: string list 20 | } 21 | with 22 | member this.TryResolve(assemblyName: string) : AssemblyInfo option = 23 | let assemblyName = if assemblyName.EndsWith(".dll") = false then assemblyName + ".dll" else assemblyName 24 | let result = 25 | if assemblyName = "FSharp.Core.dll" then 26 | Some (Path.Combine(this.FSharpCore, assemblyName)) 27 | else 28 | seq { yield! this.Directories; yield! this.Framework } 29 | |> Seq.map (fun dir -> Path.Combine(dir, assemblyName)) 30 | |> Seq.tryFindBack File.Exists 31 | result |> Option.map (fun path -> { Name = Path.GetFileNameWithoutExtension(path); Path = Path.GetFullPath(path); Implicit = false }) 32 | 33 | member this.Resolve(assemblyName: string) : AssemblyInfo = 34 | match this.TryResolve(assemblyName) with 35 | | Some path -> path 36 | | None -> raise (FileNotFoundException("Assembly is not found.", assemblyName)) 37 | 38 | member this.ResolveAll(assemblyNames: string seq) : AssemblyInfo[] = 39 | let mainAssemblies = assemblyNames |> Seq.map this.Resolve |> Seq.toArray 40 | 41 | let defaultAssemblies = 42 | [| 43 | "mscorlib.dll" 44 | |] 45 | |> Array.choose this.TryResolve 46 | |> Array.map (fun x -> { x with Implicit = true }) 47 | 48 | let mainAndDefault = Array.append mainAssemblies defaultAssemblies 49 | 50 | let resolved = Dictionary<_, _>() 51 | mainAndDefault 52 | |> Array.iter (fun a -> 53 | if resolved.ContainsKey(a.Name) = false then 54 | resolved.Add(a.Name, a) 55 | ) 56 | 57 | let rec resolveImplicitReferences (assembly: AssemblyInfo) : unit = 58 | let references = 59 | use assemblyRawFile = File.OpenRead(assembly.Path) 60 | use assemblyPeFile = new PEReader(assemblyRawFile) 61 | let assemblyReader = assemblyPeFile.GetMetadataReader() 62 | 63 | assemblyReader.AssemblyReferences 64 | |> Seq.map (fun refHandle -> 65 | let entry = assemblyReader.GetAssemblyReference(refHandle) 66 | assemblyReader.GetString(entry.Name) 67 | ) 68 | |> Seq.toArray 69 | 70 | for refName in references do 71 | if resolved.ContainsKey(refName) = false then 72 | match this.TryResolve(refName) with 73 | | Some assembly -> 74 | let assembly = { assembly with Implicit = true } 75 | resolved.Add(refName, assembly) 76 | resolveImplicitReferences assembly 77 | | None -> () 78 | 79 | mainAndDefault |> Array.iter resolveImplicitReferences 80 | 81 | resolved.Values 82 | |> Seq.toArray 83 | |> Array.sortBy (fun a -> a.Path) 84 | 85 | let internal ignoreFSharpCompilerServiceError() = 86 | typeof.Assembly.GetType("FSharp.Compiler.AbstractIL.Diagnostics") 87 | |> Option.ofObj 88 | |> Option.bind (fun diagMod -> diagMod.GetMember("diagnosticsLog", BindingFlags.NonPublic ||| BindingFlags.Static) |> Array.tryHead) 89 | |> Option.bind (tryUnbox) 90 | |> Option.bind (fun x -> x.GetValue(null) |> Option.ofObj) 91 | |> Option.bind (tryUnbox>>) 92 | |> Option.iter (fun x -> x := None) 93 | 94 | let load (references: AssemblyInfo[]) = 95 | ignoreFSharpCompilerServiceError() 96 | 97 | let checker = FSharpChecker.Create() 98 | let base1 = Path.GetTempFileName() 99 | let fileName1 = Path.ChangeExtension(base1, ".fs") 100 | let projFileName = Path.ChangeExtension(base1, ".fsproj") 101 | let dllName = Path.ChangeExtension(base1, ".dll") 102 | let options = 103 | checker.GetProjectOptionsFromCommandLineArgs 104 | (projFileName, 105 | [| 106 | yield "--simpleresolution" 107 | yield "--noframework" 108 | yield "--optimize-" 109 | yield "--out:" + dllName 110 | yield "--warn:3" 111 | yield "--fullpaths" 112 | yield "--flaterrors" 113 | yield "--target:library" 114 | yield fileName1 115 | 116 | for r in references do 117 | yield "-r:" + r.Path 118 | |] 119 | ) 120 | let refAssemblies = 121 | let x = checker.ParseAndCheckProject(options) |> Async.RunSynchronously 122 | x.ProjectContext.GetReferencedAssemblies() 123 | 124 | Array.ofList refAssemblies -------------------------------------------------------------------------------- /src/FSharpApiSearch/Database/ComputationExpressionLoader.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.ComputationExpressionLoader 2 | 3 | open FSharpApiSearch.SpecialTypes.LowType.Patterns 4 | open FSharp.Collections.ParallelSeq 5 | 6 | let (|P|) (p: Parameter) = 7 | match p.Type with 8 | | TypeAbbreviation (x, _) -> x.Original 9 | | t -> t 10 | 11 | let (|ARROW|_|) = function 12 | | Arrow (arrow, _) -> Some arrow 13 | | _ -> None 14 | 15 | module Extract = 16 | let bind (m: Member) = // M<'T> * ('T -> M<'U>) -> M<'U> 17 | match m with 18 | | { Parameters = [ [ P t1; P (ARROW ([ _], _)) ] ]; ReturnParameter = P t2 } -> [ t1; t2 ] 19 | | _ -> [] 20 | 21 | let return' (m: Member) = // 'T -> M<'T> 22 | match m with 23 | | { Parameters = [ [ _ ] ]; ReturnParameter = P t1 } -> [ t1 ] 24 | | _ -> [] 25 | 26 | let returnFrom (m: Member) = // M<'T> -> M<'T> 27 | match m with 28 | | { Parameters = [ [ P t1 ] ]; ReturnParameter = P t2 } -> [ t1; t2 ] 29 | | _ -> [] 30 | 31 | let run (m: Member) = // M<'T> -> M<'T> or M<'T> -> 'T 32 | match m with 33 | | { Parameters = [ [ _ ] ]; ReturnParameter = P t1 } -> [ t1 ] 34 | | _ -> [] 35 | 36 | let zero (m: Member) = // unit -> M<'T> 37 | match m with 38 | | { Parameters = [ [ P Unit ] ]; ReturnParameter = P t1 } -> [ t1 ] 39 | | _ -> [] 40 | 41 | let source (m: Member) = // 'T -> M<'U> 42 | match m with 43 | | { Parameters = [ [ P t1 ] ] } -> [ t1 ] 44 | | _ -> [] 45 | 46 | let customOperation (m: Member) = m.ReturnParameter.Type 47 | 48 | module BuilderMethod = 49 | let bind = function 50 | | { Name = "Bind"; Parameters = [ [ _; P (Variable _ | ARROW ([ _ ], _)) ] ]; } -> true 51 | | _ -> false 52 | 53 | let delay = function 54 | | { Name = "Delay"; Parameters = [ [ P (Variable _ | ARROW ([ (Unit | Variable _) ], _)) ] ] } -> true 55 | | _ -> false 56 | 57 | let return' = function 58 | | { Name = "Return"; Parameters = [ [ _ ] ] } -> true 59 | | _ -> false 60 | 61 | let returnFrom = function 62 | | { Name = "ReturnFrom"; Parameters = [ [ _ ] ] } -> true 63 | | _ -> false 64 | 65 | let combine = function 66 | | { Name = "Combine"; Parameters = [ [ _; _ ] ] } -> true 67 | | _ -> false 68 | 69 | let for' = function 70 | | { Name = "For"; Parameters = [ [ _; P (Variable _ | ARROW ([ _ ], _)) ] ] } -> true 71 | | _ -> false 72 | 73 | let tryFinally = function 74 | | { Name = "TryFinally"; Parameters = [ [ _; P (Variable _ | ARROW ([ (Variable _ | Unit) ], (Variable _ | Unit))) ] ] } -> true 75 | | _ -> false 76 | 77 | let tryWith = function 78 | | { Name = "TryWith"; Parameters = [ [ _; P (Variable _ | ARROW ([ _ ], _)) ] ] } -> true 79 | | _ -> false 80 | 81 | let using = function 82 | | { Name = "Using"; Parameters = [ [ _; P (Variable _ | ARROW ([ _ ], _)) ] ] } -> true 83 | | _ -> false 84 | 85 | let while' = function 86 | | { Name = "While"; Parameters = [ [ P (Variable _ | ARROW ([ (Variable _ | Unit) ], (Variable _ | Boolean) )); _ ] ] } -> true 87 | | _ -> false 88 | 89 | let yield' = function 90 | | { Name = "Yield"; Parameters = [ [ _ ] ] } -> true 91 | | _ -> false 92 | 93 | let yieldFrom = function 94 | | { Name = "YieldFrom"; Parameters = [ [ _ ] ] } -> true 95 | | _ -> false 96 | 97 | let zero = function 98 | | { Name = "Zero"; Parameters = [ [ P (Variable _ | Unit) ] ] } -> true 99 | | _ -> false 100 | 101 | let extractTypes (typeDef: FullTypeDefinition) (customOperations: seq) = 102 | seq { 103 | yield! typeDef.InstanceMembers 104 | |> Seq.collect (fun m -> 105 | match m with 106 | | { Name = "Run" } -> Extract.run m 107 | | { Name = "Bind" } -> Extract.bind m 108 | | { Name = ("Return" | "Yield") } -> Extract.return' m 109 | | { Name = ("ReturnFrom" | "YieldFrom") } -> Extract.returnFrom m 110 | | { Name = "Zero" } -> Extract.zero m 111 | | { Name = "Source" } -> Extract.source m 112 | | _ -> [] ) 113 | yield! customOperations |> Seq.map (snd >> Extract.customOperation) 114 | } 115 | |> Seq.distinct 116 | 117 | let hasMethod (builderTypeDef: FullTypeDefinition) f = builderTypeDef.InstanceMembers |> List.exists f 118 | 119 | let syntaxMethods = 120 | [ 121 | "let!", [ BuilderMethod.bind ] 122 | "yield", [ BuilderMethod.yield' ] 123 | "yield!", [ BuilderMethod.yieldFrom ] 124 | "return", [ BuilderMethod.return' ] 125 | "return!", [ BuilderMethod.returnFrom ] 126 | "use", [ BuilderMethod.using ] 127 | "use!", [ BuilderMethod.bind; BuilderMethod.using ] 128 | "if/then", [ BuilderMethod.zero ] 129 | "for", [ BuilderMethod.for' ] 130 | "while", [ BuilderMethod.while'; BuilderMethod.delay ] 131 | "try/with", [ BuilderMethod.tryWith; BuilderMethod.delay ] 132 | "try/finally", [ BuilderMethod.tryFinally; BuilderMethod.delay ] 133 | ] 134 | 135 | let hasSyntax (builderTypeDef: FullTypeDefinition) (expectedMethods: (Member -> bool) list) : bool = 136 | expectedMethods |> List.forall (hasMethod builderTypeDef) 137 | 138 | let extractSyntaxes (builderTypeDef: FullTypeDefinition) : Set = 139 | syntaxMethods 140 | |> List.choose (fun (syntax, expectedMethod) -> 141 | if hasSyntax builderTypeDef expectedMethod then 142 | Some syntax 143 | else 144 | None 145 | ) 146 | |> Set.ofList -------------------------------------------------------------------------------- /src/FSharpApiSearch/Database/Database.fs: -------------------------------------------------------------------------------- 1 | [] 2 | module FSharpApiSearch.Database 3 | 4 | open System.IO 5 | open MessagePack.Resolvers 6 | open MessagePack 7 | open MessagePack.FSharp 8 | 9 | let databaseName = "database" 10 | 11 | module internal CompactImpl = 12 | open System.Collections.Generic 13 | 14 | let visit (assemblies: HashSet) (t: LowType) = 15 | let rec collectAssemblyName = function 16 | | Wildcard _ -> () 17 | | Variable _ -> () 18 | | Identifier (ConcreteType c, _) -> assemblies.Add(c.AssemblyName) |> ignore 19 | | Identifier (UserInputType _, _) -> () 20 | | Arrow ((ps, ret), _) -> List.iter collectAssemblyName ps; collectAssemblyName ret 21 | | Tuple (t, _) -> List.iter collectAssemblyName t.Elements 22 | | Generic (id, args, _) -> collectAssemblyName id; List.iter collectAssemblyName args 23 | | TypeAbbreviation (t, _) -> collectAssemblyName t.Abbreviation; collectAssemblyName t.Original 24 | | Delegate (d, (ps, ret), _) -> collectAssemblyName d; List.iter collectAssemblyName ps; collectAssemblyName ret 25 | | ByRef (_, t, _) -> collectAssemblyName t 26 | | Subtype _ | Choice _ | LoadingType _ -> () 27 | collectAssemblyName t 28 | t 29 | 30 | let rec collectUsedAssemblyNames (database: Database) (usedAssemblies: Set) (testAssemblies: Set) : Set = 31 | testAssemblies 32 | |> Seq.fold (fun state testAssemblyName -> 33 | if state.Contains(testAssemblyName) then 34 | state 35 | else 36 | let before = state |> Set.add testAssemblyName 37 | let testAssembly = database |> Array.find (fun d -> d.AssemblyName = testAssemblyName) 38 | let after = 39 | let result = HashSet(before) 40 | testAssembly.Api |> Array.iter (LowTypeVisitor.accept_Api (visit result) >> ignore) 41 | Set(result) 42 | let newAssemblies = after - before 43 | collectUsedAssemblyNames database before newAssemblies 44 | ) usedAssemblies 45 | 46 | let removeUnusedAssembly (mainAssemblies: Set) (database: Database) = 47 | let usedAssemblies = collectUsedAssemblyNames database Set.empty mainAssemblies 48 | database 49 | |> Array.filter (fun apiDict -> usedAssemblies.Contains(apiDict.AssemblyName)) 50 | 51 | let implicitAssemblyIsOnlyTypeDef (mainAssemblies: Set) (apiDict: ApiDictionary) = 52 | if mainAssemblies.Contains(apiDict.AssemblyName) then 53 | apiDict 54 | else 55 | { apiDict with 56 | Api = apiDict.Api |> Array.filter (fun api -> match api.Signature with ApiSignature.FullTypeDefinition _ | ApiSignature.TypeAbbreviation _ -> true | _ -> false) 57 | } 58 | let compact (assemblies: AssemblyLoader.AssemblyInfo[]) (database: Database) : Database = 59 | let mainAssemblies = assemblies |> Array.choose (fun x -> if not x.Implicit then Some x.Name else None) |> Set 60 | 61 | database 62 | |> Array.map (implicitAssemblyIsOnlyTypeDef mainAssemblies) 63 | |> removeUnusedAssembly mainAssemblies 64 | 65 | let compact (assemblies: AssemblyLoader.AssemblyInfo[]) (database: Database) : Database = CompactImpl.compact assemblies database 66 | 67 | module internal Serialization = 68 | type T = (string * Api[])[] 69 | let toDumpObj (xs: Database) : T = xs |> Array.map (fun x -> x.AssemblyName, x.Api) 70 | 71 | let fromDumpObj (xs: T) : Database = 72 | xs 73 | |> Array.map (fun (name, apis) -> 74 | { AssemblyName = name; Api = apis; TypeDefinitions = IDictionary.empty; TypeAbbreviations = Array.empty } 75 | |> ApiLoader.Impl.makeDefAndAbb 76 | ) 77 | 78 | let internal messagePackOptions = 79 | let resolver = 80 | { new IFormatterResolver with 81 | member _.GetFormatter<'T>() = 82 | match FSharpResolver.Instance.GetFormatter<'T>() with 83 | | null -> StandardResolver.Instance.GetFormatter<'T>() 84 | | x -> x 85 | } 86 | MessagePackSerializerOptions.Standard.WithResolver(resolver) 87 | 88 | let saveStream (stream: Stream) (database: Database) : unit = 89 | MessagePackSerializer.Serialize(stream, Serialization.toDumpObj database, messagePackOptions) 90 | 91 | let save (path: string) (database: Database) : unit = 92 | if File.Exists(path) then File.Delete(path) 93 | use file = File.OpenWrite(path) 94 | saveStream file database 95 | 96 | let loadFromStream (stream: Stream) : Database = 97 | MessagePackSerializer.Deserialize(stream, messagePackOptions) |> Serialization.fromDumpObj 98 | 99 | let loadFromFile (path: string) : Database = 100 | use file = File.OpenRead(path) 101 | loadFromStream file -------------------------------------------------------------------------------- /src/FSharpApiSearch/Database/Hack.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.Hack 2 | 3 | open FSharp.Compiler.Symbols 4 | 5 | let genericArguments (t: FSharpType) = 6 | let args = t.GenericArguments |> Seq.toList 7 | args 8 | 9 | let isAbbreviation (t: FSharpType) = t.IsAbbreviation 10 | 11 | let isMeasure (t: FSharpType) = t.HasTypeDefinition && t.TypeDefinition.IsMeasure // HACK: The herz measure is infinit loop of type abbreviation. 12 | 13 | let isUnitOnlyParameter (x: FSharpMemberOrFunctionOrValue) = // CurriedParameterGroups of the parameter is unit only (`member _.X : unit -> int`) is [ [] ] 14 | Seq.length x.CurriedParameterGroups = 1 && Seq.length (Seq.item 0 x.CurriedParameterGroups) = 0 15 | 16 | let isTupleType (t: FSharpType) = 17 | if t.HasTypeDefinition then 18 | let td = t.TypeDefinition 19 | td.TryFullName |> Option.exists (fun name -> name.StartsWith("System.Tuple`") || name.StartsWith("System.ValueTuple`")) 20 | else 21 | t.IsTupleType 22 | 23 | let isStructTupleType (t: FSharpType) = 24 | if t.HasTypeDefinition then 25 | let td = t.TypeDefinition 26 | td.TryFullName |> Option.exists (fun name -> name.StartsWith("System.ValueTuple`")) 27 | else 28 | t.IsStructTupleType -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/ContextInitializer.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.ContextInitializer 2 | 3 | open EngineTypes 4 | 5 | let collectFromSignatureQuery (|Target|_|) query = 6 | let results = ResizeArray() 7 | let add x = results.Add(x) 8 | 9 | let rec f = function 10 | | Target x -> add x 11 | | Identifier _ | Wildcard _ | Variable _ -> () 12 | | Arrow ((ps, ret), _) -> List.iter f ps; f ret 13 | | Tuple ({ Elements = xs }, _) -> List.iter f xs 14 | | Generic (id, args, _) -> f id; List.iter f args 15 | | TypeAbbreviation ({ Original = o }, _) -> f o 16 | | ByRef (_, t, _) -> f t 17 | | Choice (_, xs, _) -> List.iter f xs 18 | | Delegate (t, _, _) -> f t 19 | | LowType.Subtype (t, _) -> f t 20 | | LoadingType _ -> Name.loadingNameError() 21 | 22 | match query with 23 | | { Query.Method = QueryMethod.ByName (_, sigQuery) } 24 | | { Query.Method = QueryMethod.BySignature sigQuery } 25 | | { Query.Method = QueryMethod.ByNameOrSignature (_, sigQuery) }-> 26 | match sigQuery with 27 | | SignatureQuery.Wildcard -> () 28 | | SignatureQuery.Signature lt -> f lt 29 | | { Query.Method = QueryMethod.ByActivePattern apQuery } -> 30 | match apQuery with 31 | | { ActivePatternQuery.Signature = ActivePatternSignature.AnyParameter (x, y) } -> f x; f y 32 | | { ActivePatternQuery.Signature = ActivePatternSignature.Specified x } -> f x 33 | | { Query.Method = QueryMethod.ByComputationExpression ceQuery } -> f ceQuery.Type 34 | 35 | results |> Seq.distinct |> Seq.toList 36 | 37 | let collectVariables = collectFromSignatureQuery (function Variable _ as v -> Some v | _ -> None) 38 | let collectWildcardGroups = collectFromSignatureQuery (function Wildcard (Some _, _) as w -> Some w | _ -> None) 39 | let collectUserInputTypes = collectFromSignatureQuery (function Identifier (UserInputType id, _) -> Some id | _ -> None) 40 | 41 | let initialEquations options query eqs = 42 | match options.RespectNameDifference with 43 | | Enabled -> 44 | let variables = collectVariables query 45 | let wildcards = collectWildcardGroups query 46 | let inequalities = 47 | [ 48 | for x in variables do 49 | for y in variables do 50 | if x < y then yield (x, y) 51 | 52 | for x in wildcards do 53 | for y in wildcards do 54 | if x < y then yield (x, y) 55 | ] 56 | { eqs with Inequalities = inequalities } 57 | | Disabled -> eqs 58 | 59 | let queryTypes query (dictionaries: ApiDictionary[]) = 60 | collectUserInputTypes query 61 | |> Seq.map (fun id -> 62 | let types = 63 | dictionaries 64 | |> Seq.collect (fun d -> d.TypeDefinitions.Values) 65 | |> Seq.filter (fun td -> TypeNameEquality.sameName (UserInputType id) (ConcreteType td.ConcreteType) = Ok 0) 66 | |> Seq.toArray 67 | (id, types) 68 | ) 69 | |> Map.ofSeq 70 | 71 | let initializeContext (dictionaries: ApiDictionary[]) (options: SearchOptions) (query: Query) = 72 | { 73 | Distance = 0 74 | Equations = Equations.empty |> initialEquations options query 75 | MatchPositions = Map.empty 76 | QueryTypes = queryTypes query dictionaries 77 | ApiDictionaries = dictionaries |> Seq.map (fun d -> (d.AssemblyName, d)) |> dict 78 | SubtypeCache = SubtypeCache.create() 79 | } -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Engine.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.Engine 2 | 3 | open FSharpApiSearch.EngineTypes 4 | 5 | let internal test (lowTypeMatcher: ILowTypeMatcher) (apiMatchers: IApiMatcher[]) (query: Query) (ctx: Context) (api: Api) = 6 | let mutable continue' = true 7 | let mutable state = ctx 8 | let mutable index = 0 9 | 10 | while continue' && index < apiMatchers.Length do 11 | let m = apiMatchers.[index] 12 | index <- index + 1 13 | 14 | let result = ApiMatcher.test lowTypeMatcher m query api state 15 | 16 | match result with 17 | | Matched ctx -> state <- ctx 18 | | _ -> continue' <- false 19 | 20 | if continue' then 21 | Matched state 22 | else 23 | Failure FailureInfo.None 24 | 25 | let internal search' (seqFunc: SeqFunctions) (targets: ApiDictionary seq) (lowTypeMatcher: ILowTypeMatcher) (apiMatchers: IApiMatcher[]) (query: Query) (initialContext: Context) = 26 | targets 27 | |> Seq.collect (fun dic -> dic.Api |> Seq.map (fun api -> (dic, api))) 28 | |> seqFunc.Choose (fun (dic, api) -> 29 | match test lowTypeMatcher apiMatchers query initialContext api with 30 | | Matched ctx -> Some { Distance = ctx.Distance; Api = api; AssemblyName = dic.AssemblyName; MatchPositions = ctx.MatchPositions } 31 | | _ -> None 32 | ) 33 | 34 | let search (dictionaries: ApiDictionary[]) (options: SearchOptions) (targets: ApiDictionary seq) (queryStr: string) : Query * seq = 35 | let strategy = EngineStrategy.create options 36 | let query = strategy.InitializeQuery(strategy.ParseQuery(queryStr), dictionaries) 37 | let lowTypeMatcher, apiMatchers = strategy.Matchers(query) 38 | let initialContext = strategy.InitialContext(query, dictionaries) 39 | 40 | let results = 41 | match query.Method with 42 | | QueryMethod.ByComputationExpression ceQuery -> ComputationExpressionMatcher.search strategy.SeqFunctions targets lowTypeMatcher ceQuery initialContext 43 | | _ -> search' strategy.SeqFunctions targets lowTypeMatcher apiMatchers query initialContext 44 | 45 | (query, results) -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/EngineDebug.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch 2 | 3 | open System.Diagnostics 4 | 5 | module internal EngineDebug = 6 | [] 7 | let Configuration = "EngineDebug" 8 | 9 | type internal EngineDebug private () = 10 | [] 11 | static member Indent() = Debug.Indent() 12 | 13 | [] 14 | static member Unindent() = Debug.Unindent() 15 | 16 | [] 17 | static member WriteLine(message: string) = Debug.WriteLine(message) -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/EngineStrategy.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch 2 | 3 | open EngineTypes 4 | 5 | type internal EngineStrategy = 6 | abstract Matchers: Query -> ILowTypeMatcher * IApiMatcher[] 7 | abstract ParseQuery: string -> Query 8 | abstract InitializeQuery: Query * ApiDictionary[] -> Query 9 | abstract InitialContext: Query * ApiDictionary[] -> Context 10 | abstract SeqFunctions: SeqFunctions 11 | 12 | module internal EngineStrategy = 13 | 14 | let buildMatchers options apiMatchers = 15 | let lowTypeMatcher = LowTypeMatcher.instance options 16 | let apiMatchers = apiMatchers |> Array.map (fun f -> f options) 17 | (lowTypeMatcher, apiMatchers) 18 | 19 | open QueryInitializer 20 | open ContextInitializer 21 | 22 | type FSharp(options: SearchOptions) = 23 | interface EngineStrategy with 24 | member this.Matchers(query) = 25 | [| 26 | match query.Method with 27 | | QueryMethod.ByName _ -> 28 | yield NameMatcher.instance 29 | yield SignatureMatcher.instance 30 | | QueryMethod.BySignature _ -> 31 | yield SignatureMatcher.instance 32 | | QueryMethod.ByNameOrSignature _ -> 33 | yield NameOrSignatureMatcher.instance 34 | | QueryMethod.ByActivePattern _ -> 35 | yield ActivePatternMatcher.instance 36 | | QueryMethod.ByComputationExpression _ -> 37 | yield ComputationExpressionMatcher.Filter.instance 38 | 39 | match options.GreedyMatching with 40 | | Enabled -> 41 | yield ConstraintSolver.instance 42 | | Disabled -> () 43 | |] 44 | |> buildMatchers options 45 | member this.ParseQuery(queryStr) = QueryParser.FSharp.parse queryStr 46 | member this.InitializeQuery(query, dictionaries) = 47 | let table = typeAbbreviationTableFromApiDictionary dictionaries 48 | initializeQuery options table query 49 | member this.InitialContext(query, dictionaries) = initializeContext dictionaries options query 50 | member val SeqFunctions = SeqFunctions.create options with get 51 | 52 | let csharpAliases = 53 | SpecialTypes.Identifier.CSharp.aliases 54 | |> List.map (fun (alias, original) -> 55 | let alias = Identifier.create (UserInputType { Name = Name.ofString alias }) 56 | let original = Identifier.create original 57 | { Abbreviation = alias; Original = original }) 58 | 59 | type CSharp(options: SearchOptions) = 60 | interface EngineStrategy with 61 | member this.Matchers(query) = 62 | [| 63 | yield CSharpFilter.instance 64 | 65 | match query.Method with 66 | | QueryMethod.ByName _ -> 67 | yield NameMatcher.instance 68 | yield SignatureMatcher.instance 69 | | QueryMethod.BySignature _ -> 70 | yield SignatureMatcher.instance 71 | | QueryMethod.ByNameOrSignature _ -> 72 | yield NameOrSignatureMatcher.instance 73 | | QueryMethod.ByActivePattern _ -> () 74 | | QueryMethod.ByComputationExpression _ -> () 75 | |] 76 | |> buildMatchers options 77 | member this.ParseQuery(queryStr) = QueryParser.CSharp.parse queryStr 78 | member this.InitializeQuery(query, _) = initializeQuery options csharpAliases query 79 | member this.InitialContext(query, dictionaries) = initializeContext dictionaries options query 80 | member val SeqFunctions = SeqFunctions.create options with get 81 | 82 | let internal create options : EngineStrategy = 83 | match options.Language with 84 | | FSharp -> FSharp(options) :> _ 85 | | CSharp -> CSharp(options) :> _ -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/EngineTypes.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.EngineTypes 2 | 3 | open System.Collections.Generic 4 | open FSharpApiSearch 5 | open FSharpApiSearch.StringPrinter 6 | open System.Collections.Concurrent 7 | 8 | type Equations = { 9 | Equalities: (LowType * LowType) list 10 | Inequalities: (LowType * LowType) list 11 | } 12 | 13 | module Equations = 14 | let debugEquality (left, right) = LowType.debug left + " = " + LowType.debug right 15 | let debugInequality (left, right) = LowType.debug left + " <> " + LowType.debug right 16 | let debug x = sprintf "Equalities = %A, Inequalities = %A" (List.map debugEquality x.Equalities) (List.map debugInequality x.Inequalities) 17 | 18 | let empty = { Equalities = []; Inequalities = [] } 19 | 20 | type SubtypeResult = 21 | | Subtype of LowType 22 | | MaybeSubtype of LowType 23 | | NotSubtype 24 | 25 | type SubtypeCache = ConcurrentDictionary 26 | 27 | module SubtypeCache = 28 | let create() = SubtypeCache() 29 | 30 | type Distance = int 31 | 32 | type Context = { 33 | Distance: Distance 34 | Equations: Equations 35 | MatchPositions: Map 36 | QueryTypes: Map 37 | ApiDictionaries: IDictionary 38 | SubtypeCache: SubtypeCache 39 | } 40 | 41 | module Context = 42 | let addDistance reason x (ctx: Context) = 43 | let newDistance = ctx.Distance + x 44 | EngineDebug.WriteLine(sprintf "Update distance from %d to %d by %s" ctx.Distance newDistance reason) 45 | { ctx with Distance = newDistance } 46 | 47 | let newEquations (oldCtx: Context) (newCtx: Context) = 48 | newCtx.Equations.Equalities |> List.take (newCtx.Equations.Equalities.Length - oldCtx.Equations.Equalities.Length) 49 | 50 | [] 51 | type FailureInfo = 52 | | None 53 | | GenericArgumentsMismatch 54 | | Many of FailureInfo list 55 | 56 | [] 57 | type MatchingResult = 58 | | Matched of ctx:Context 59 | | Continue 60 | | Failure of info:FailureInfo 61 | 62 | module MatchingResult = 63 | let inline bindMatched f x = match x with Matched x -> f x | r -> r 64 | let inline mapMatched f x = match x with Matched x -> Matched (f x) | Continue -> Continue | Failure _ as failure -> failure 65 | 66 | let toBool = function Matched _ -> true | _ -> false 67 | 68 | type ILowTypeMatcher = 69 | abstract Test: LowType -> LowType -> Context -> MatchingResult 70 | abstract TestAll: LowType seq -> LowType seq -> Context -> MatchingResult 71 | abstract TestAllExactly: LowType seq -> LowType seq -> Context -> MatchingResult 72 | 73 | [] 74 | module Extensions = 75 | type ILowTypeMatcher with 76 | member this.TestArrow (left: Arrow) (right: Arrow) (ctx: Context) = 77 | this.Test (snd left) (snd right) ctx 78 | |> MatchingResult.bindMatched (this.TestAll (fst left) (fst right)) 79 | 80 | member this.TestReceiver (left: LowType) (right: LowType) (ctx: Context) = 81 | match left, right with 82 | | Tuple _, Tuple _ -> this.Test left right ctx 83 | | Tuple _, _ | _, Tuple _ -> Failure FailureInfo.None 84 | | _ -> this.Test left right ctx 85 | 86 | type IApiMatcher = 87 | abstract Name: string 88 | abstract Test: ILowTypeMatcher -> Query -> Api -> Context -> MatchingResult 89 | 90 | module ApiMatcher = 91 | let test (lowTypeMatcher: ILowTypeMatcher) (apiMatcher: IApiMatcher) (query: Query) (api: Api) (ctx: Context) = 92 | EngineDebug.WriteLine(sprintf "Test \"%s\" and \"%s\" by %s. Equations: %s" 93 | query.OriginalString 94 | (ApiSignature.debug api.Signature) 95 | apiMatcher.Name 96 | (Equations.debug ctx.Equations)) 97 | EngineDebug.Indent() 98 | let result = apiMatcher.Test lowTypeMatcher query api ctx 99 | EngineDebug.Unindent() 100 | result 101 | 102 | type Rule<'Matcher, 'Left, 'Right> = 'Matcher -> 'Left -> 'Right -> Context -> MatchingResult 103 | 104 | module Rule = 105 | let run (rule: Rule<_, _, _>) matcher left right ctx = rule matcher left right ctx 106 | let terminator _ _ _ _ : MatchingResult = 107 | EngineDebug.WriteLine("It reached the terminator.") 108 | Failure FailureInfo.None 109 | let failureToContinue (rule: Rule<_, _, _>) matcher left right ctx = 110 | match run rule matcher left right ctx with 111 | | Failure _ -> Continue 112 | | (Matched _ | Continue _) as result -> result 113 | let compose (xs: Rule<_, _, _>[]): Rule<_, _, _> = 114 | fun test left right ctx -> 115 | let mutable continue' = true 116 | let mutable state = ctx 117 | let mutable result = Continue 118 | let mutable index = 0 119 | while continue' && index < xs.Length do 120 | let rule = xs.[index] 121 | index <- index + 1 122 | let newResult = run rule test left right state 123 | result <- newResult 124 | match newResult with 125 | | Continue -> () 126 | | _ -> continue' <- false 127 | result 128 | 129 | type SeqFunctions = 130 | abstract Choose : ('a -> 'b option) -> seq<'a> -> seq<'b> 131 | abstract Collect : ('a -> seq<'b>) -> seq<'a> -> seq<'b> 132 | 133 | module SeqFunctions = 134 | open FSharp.Collections.ParallelSeq 135 | let parallel' = 136 | { new SeqFunctions with 137 | member this.Choose f xs = PSeq.choose f xs :> seq<_> 138 | member this.Collect f xs = PSeq.collect f xs :> seq<_> 139 | } 140 | let serial = 141 | { new SeqFunctions with 142 | member this.Choose f xs = Seq.choose f xs 143 | member this.Collect f xs = Seq.collect f xs 144 | } 145 | let create (options: SearchOptions) = 146 | match options.Parallel with 147 | | Enabled -> parallel' 148 | | Disabled -> serial -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/ActivePatternMatcher.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.ActivePatternMatcher 2 | 3 | open FSharpApiSearch.EngineTypes 4 | 5 | let testAllParameter (lowTypeMatcher: ILowTypeMatcher) activePatternType returnType (right: Function) ctx = 6 | let left = Arrow.create ([ activePatternType ], returnType) 7 | let right = 8 | let ps, ret = Function.toArrow right 9 | Arrow.create ([ List.last ps ], ret) 10 | lowTypeMatcher.Test left right ctx 11 | 12 | let test (lowTypeMatcher: ILowTypeMatcher) (query: ActivePatternQuery) (api: Api) ctx = 13 | match api.Signature with 14 | | ApiSignature.ActivePatten (kind, right) when query.Kind = kind -> 15 | match query.Signature with 16 | | ActivePatternSignature.AnyParameter (activePatternType, returnType) -> 17 | testAllParameter lowTypeMatcher activePatternType returnType right ctx 18 | | ActivePatternSignature.Specified left -> 19 | let right = Arrow.create (Function.toArrow right) 20 | lowTypeMatcher.Test left right ctx 21 | | _ -> Failure FailureInfo.None 22 | 23 | let instance (_: SearchOptions) = 24 | { new IApiMatcher with 25 | member this.Name = "Active Pattern Matcher" 26 | member this.Test lowTypeMatcher query api ctx = 27 | match query.Method with 28 | | QueryMethod.ByActivePattern activePatternQuery -> test lowTypeMatcher activePatternQuery api ctx 29 | | _ -> Matched ctx } -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/CSharpFilter.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.CSharpFilter 2 | 3 | open EngineTypes 4 | 5 | let test api ctx = 6 | match api.Signature with 7 | | ApiSignature.ModuleValue _ 8 | | ApiSignature.ModuleFunction _ 9 | | ApiSignature.InstanceMember _ 10 | | ApiSignature.StaticMember _ 11 | | ApiSignature.Constructor _ 12 | | ApiSignature.FullTypeDefinition _ 13 | | ApiSignature.ExtensionMember _ -> Matched ctx 14 | 15 | | ApiSignature.ActivePatten _ 16 | | ApiSignature.ModuleDefinition _ 17 | | ApiSignature.TypeAbbreviation _ 18 | | ApiSignature.TypeExtension _ 19 | | ApiSignature.UnionCase _ 20 | | ApiSignature.ComputationExpressionBuilder _ -> Failure FailureInfo.None 21 | 22 | let instance (_: SearchOptions) = 23 | { new IApiMatcher with 24 | member this.Name = "CSharp Filter" 25 | member this.Test lowTypeMatcher query api ctx = test api ctx } -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/ComputationExpressionMatcher.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.ComputationExpressionMatcher 2 | 3 | open EngineTypes 4 | 5 | module Filter = 6 | let instance (_: SearchOptions) = 7 | { new IApiMatcher with 8 | member this.Name = "Computation Expression Filter" 9 | member this.Test lowTypeMatcher query api ctx = 10 | match api.Kind with 11 | | ApiKind.ComputationExpressionBuilder -> Failure FailureInfo.None 12 | | _ -> Matched ctx } 13 | 14 | type ComputationExpressionBuilderRule = ILowTypeMatcher -> ComputationExpressionQuery -> ComputationExpressionBuilder -> Context -> MatchingResult 15 | 16 | let ceBuilderTypeRule (lowTypeMatcher: ILowTypeMatcher) (query: ComputationExpressionQuery) (builder: ComputationExpressionBuilder) ctx = 17 | let right = Choice.create (builder.BuilderType, builder.ComputationExpressionTypes) 18 | lowTypeMatcher.Test query.Type right ctx 19 | 20 | let syntaxRule (_: ILowTypeMatcher) (query: ComputationExpressionQuery) (builder: ComputationExpressionBuilder) ctx = 21 | let builderSyntaxes = builder.Syntaxes |> List.map (fun s -> s.Syntax, s.Position) |> dict 22 | query.Syntaxes 23 | |> List.fold (fun result querySyntax -> 24 | result 25 | |> MatchingResult.bindMatched (fun ctx -> 26 | match builderSyntaxes.TryGetValue querySyntax.Syntax with 27 | | true, sigPos -> 28 | let newCtx = 29 | match querySyntax.Position, sigPos with 30 | | AtQuery (Some queryId, _), AtSignature sigId -> { ctx with MatchPositions = Map.add sigId queryId ctx.MatchPositions } 31 | | _ -> ctx 32 | Matched newCtx 33 | | _ -> Failure FailureInfo.None 34 | ) 35 | ) (Matched ctx) 36 | 37 | let ceBuilderRules : ComputationExpressionBuilderRule = fun lowTypeMatcher query builder ctx -> 38 | Rule.run ceBuilderTypeRule lowTypeMatcher query builder ctx 39 | |> MatchingResult.bindMatched (Rule.run syntaxRule lowTypeMatcher query builder) 40 | 41 | let test (lowTypeMatcher: ILowTypeMatcher) (builderTypes: LowType) (ctx: Context) (api: Api) = 42 | match api.Signature with 43 | | ApiSignature.ModuleValue (TypeAbbreviation ({ Original = Arrow ((_, ret), _) }, _)) -> lowTypeMatcher.Test builderTypes ret ctx 44 | | ApiSignature.ModuleValue value -> lowTypeMatcher.Test builderTypes value ctx 45 | | ApiSignature.ModuleFunction (_, ret) -> lowTypeMatcher.Test builderTypes ret.Type ctx 46 | | _ -> Failure FailureInfo.None 47 | 48 | let search (seqFunc: SeqFunctions) (targets: ApiDictionary seq) (lowTypeMatcher: ILowTypeMatcher) (query: ComputationExpressionQuery) (initialContext: Context) = 49 | let builderTypes = 50 | targets 51 | |> seqFunc.Collect (fun target -> seq { 52 | for api in target.Api do 53 | match api.Signature with 54 | | ApiSignature.ComputationExpressionBuilder builder -> 55 | match Rule.run ceBuilderRules lowTypeMatcher query builder initialContext with 56 | | Matched ctx -> 57 | let result = { Distance = ctx.Distance; Api = api; AssemblyName = target.AssemblyName; MatchPositions = ctx.MatchPositions } 58 | yield (result, builder.BuilderType) 59 | | _ -> () 60 | | _ -> () 61 | }) 62 | |> Seq.toList 63 | 64 | 65 | if List.isEmpty builderTypes then 66 | Seq.empty 67 | else 68 | let builderResults = builderTypes |> List.map fst 69 | 70 | let builderTypes = Choice.create (query.Type, builderTypes |> List.map snd) 71 | 72 | let apiResults = 73 | targets 74 | |> Seq.collect (fun dic -> dic.Api |> Seq.map (fun api -> (dic, api))) 75 | |> seqFunc.Choose (fun (dic, api) -> 76 | match test lowTypeMatcher builderTypes initialContext api with 77 | | Matched ctx -> Some { Distance = ctx.Distance; Api = api; AssemblyName = dic.AssemblyName; MatchPositions = ctx.MatchPositions } 78 | | _ -> None 79 | ) 80 | 81 | Seq.append builderResults apiResults -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/NameMatcher.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.NameMatcher 2 | 3 | open FSharpApiSearch.EngineTypes 4 | open System.Text.RegularExpressions 5 | open System 6 | 7 | open TypeNameEquality 8 | 9 | type StringOptions = { 10 | DefaultTestString: string -> string -> Result 11 | StringComparison: StringComparison 12 | RegexOptions: RegexOptions 13 | } 14 | 15 | let stringOptions options = 16 | let stringComparison, regexOptions = 17 | match options.IgnoreCase with 18 | | Enabled -> StringComparison.InvariantCultureIgnoreCase, RegexOptions.CultureInvariant ||| RegexOptions.IgnoreCase 19 | | Disabled -> StringComparison.InvariantCulture, RegexOptions.CultureInvariant 20 | let testString = 21 | match options.Substring with 22 | | Enabled -> testStringSubstring 23 | | Disabled -> testStringExact 24 | { 25 | DefaultTestString = testString stringComparison 26 | StringComparison = stringComparison 27 | RegexOptions = regexOptions 28 | } 29 | 30 | let private cmp strOpt (byName: ByName) (actual: string) = 31 | let expected = byName.Expected 32 | let boolToResult b = if b then Ok 0 else Error FailureReason.DifferentName 33 | match byName.MatchMethod with 34 | | NameMatchMethod.Equals -> actual.Equals(expected, strOpt.StringComparison) |> boolToResult 35 | | NameMatchMethod.Default -> strOpt.DefaultTestString expected actual 36 | | NameMatchMethod.StartsWith -> actual.StartsWith(expected, strOpt.StringComparison) |> boolToResult 37 | | NameMatchMethod.EndsWith -> actual.EndsWith(expected, strOpt.StringComparison) |> boolToResult 38 | | NameMatchMethod.Contains -> actual.IndexOf(expected, strOpt.StringComparison) >= 0 |> boolToResult 39 | | NameMatchMethod.Regex -> Regex.IsMatch(actual, expected, strOpt.RegexOptions) |> boolToResult 40 | | NameMatchMethod.Any -> Ok 0 41 | 42 | let testGenericParameterLength (byName: ByName) (actual: NameItem) = 43 | let expectedLen = byName.GenericParameters.Length 44 | if expectedLen > 0 then 45 | let actualLen = actual.GenericParameters.Length 46 | if expectedLen = actualLen then 47 | Ok 0 48 | else 49 | Error (FailureReason.DifferentGenericParameter (expectedLen, actualLen)) 50 | else 51 | Ok 0 52 | 53 | 54 | let testByName strOpt (expected: ByName list) (actualNames: NameItem list) = 55 | if not (List.length expected <= List.length actualNames) then 56 | Error FailureReason.DifferentName 57 | else 58 | let test' (byName: ByName) (actualName: NameItem) = test { 59 | do! cmp strOpt byName (testee actualName) 60 | do! testGenericParameterLength byName actualName 61 | } 62 | forall2 test' expected actualNames 63 | 64 | let ctor = { Name = SymbolName ".ctor"; GenericParameters = [] } 65 | 66 | let test strOpt query (api: Api) ctx = 67 | match query with 68 | | QueryMethod.ByName (expected, _) | QueryMethod.ByNameOrSignature (expected, _) -> 69 | match api.Name, api.Kind with 70 | | ApiName actualName, ApiKind.Constructor -> 71 | // {TypeName} or {TypeName}.new or {TypeName}..ctor 72 | let constructors = [| actualName.Tail; actualName; (ctor :: actualName.Tail) |] 73 | let result = 74 | constructors 75 | |> Array.tryPick (fun constructorName -> 76 | match testByName strOpt expected constructorName with 77 | | Ok distance -> Some distance 78 | | Error _ -> None 79 | ) 80 | match result with 81 | | Some distance -> Matched (ctx |> Context.addDistance "name matching" distance) 82 | | None -> Failure FailureInfo.None 83 | | ApiName actualName, _ -> 84 | match testByName strOpt expected actualName with 85 | | Ok distance -> Matched (ctx |> Context.addDistance "name matching" distance) 86 | | Error _ -> Failure FailureInfo.None 87 | | _ -> Failure FailureInfo.None 88 | | _ -> Matched ctx 89 | 90 | let instance (options: SearchOptions) = 91 | let strOpt = stringOptions options 92 | { new IApiMatcher with 93 | member this.Name = "Name Matcher" 94 | member this.Test lowTypeMatcher query api ctx = test strOpt query.Method api ctx } -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/NameOrSignatureMatcher.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.NameOrSignatureMatcher 2 | 3 | open EngineTypes 4 | 5 | let instance (options: SearchOptions) = 6 | let nameMatcher = NameMatcher.instance options 7 | let sigMatcher = SignatureMatcher.instance options 8 | { new IApiMatcher with 9 | member this.Name = "Name or Signature Matcher" 10 | member this.Test lowTypeMatcher query api ctx = 11 | let nameResult = ApiMatcher.test lowTypeMatcher nameMatcher query api ctx 12 | match nameResult with 13 | | Matched _ as m -> m 14 | | _ -> ApiMatcher.test lowTypeMatcher sigMatcher query api ctx 15 | } -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/NonPublicFilter.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.NonPublicFilter 2 | 3 | open EngineTypes 4 | 5 | let testAccessibility ctx = function 6 | | Public -> Matched ctx 7 | | Private -> Failure FailureInfo.None 8 | 9 | let test api ctx = 10 | match api.Signature with 11 | | ApiSignature.FullTypeDefinition { Accessibility = accessibility } 12 | | ApiSignature.TypeAbbreviation { Accessibility = accessibility } 13 | | ApiSignature.ModuleDefinition { Accessibility = accessibility } -> testAccessibility ctx accessibility 14 | | _ -> Matched ctx 15 | 16 | let instance (_: SearchOptions) = 17 | { new IApiMatcher with 18 | member this.Name = "Non Public Filter" 19 | member this.Test lowTypeMatcher query api ctx = test api ctx } -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/TypeHierarchy.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.TypeHierarchy 2 | 3 | open FSharpApiSearch.EngineTypes 4 | open StringPrinter 5 | 6 | let transferVariableArgument (inheritArgs: Map) (baseType: LowType): LowType list = 7 | let rec genericArguments = function 8 | | Identifier _ -> [] 9 | | Generic (_, args, _) -> args 10 | | TypeAbbreviation ({ Original = o }, _) -> genericArguments o 11 | | _ -> failwith "invalid base type." 12 | genericArguments baseType 13 | |> List.map (function 14 | | Variable (VariableSource.Target, v, _) -> inheritArgs.[v] 15 | | a -> a) 16 | 17 | let instantiate (t: FullTypeDefinition) (args: LowType list) = 18 | let id = Identifier.create (ConcreteType t.ConcreteType) 19 | match args with 20 | | [] -> id 21 | | _ -> Generic.create (id, args) 22 | 23 | let fullTypeDefOfConcreteType (ctx: Context) (concreteType: ConcreteType) = 24 | let assemblyName = concreteType.AssemblyName 25 | match ctx.ApiDictionaries.TryGetValue(assemblyName) with 26 | | true, apiDict -> 27 | match apiDict.TypeDefinitions.TryGetValue(concreteType) with 28 | | true, typeDef -> typeDef 29 | | false, _ -> failwithf """type %s" in "%s" is not found.""" (concreteType.Name.Print()) assemblyName 30 | | false, _ -> failwithf """Assembly "%s" is not found.""" assemblyName 31 | 32 | let rec getBaseTypes (ctx: Context) (t: FullTypeDefinition) (args: LowType list): LowType seq = seq { 33 | let argPair = Map.ofList2 t.GenericParameters args 34 | 35 | let thisType = instantiate t args 36 | yield thisType 37 | 38 | let parents = seq { 39 | yield! t.AllInterfaces 40 | 41 | match t.BaseType with 42 | | Some baseType -> yield baseType 43 | | None -> () 44 | } 45 | 46 | for p in parents do 47 | let baseTypeArgs = transferVariableArgument argPair p 48 | let baseTypeDef = 49 | let rec getConcreteType = function 50 | | Identifier (ConcreteType full, _) -> full 51 | | Generic (Identifier (ConcreteType full, _), _, _) -> full 52 | | TypeAbbreviation ({ Original = o }, _) -> getConcreteType o 53 | | _ -> failwith "It is not concrete type." 54 | getConcreteType p 55 | |> fullTypeDefOfConcreteType ctx 56 | yield! getBaseTypes ctx baseTypeDef baseTypeArgs 57 | } 58 | 59 | let fullTypeDef (ctx: Context) = function 60 | | ConcreteType i -> [| fullTypeDefOfConcreteType ctx i |] 61 | | UserInputType i -> ctx.QueryTypes.[i] -------------------------------------------------------------------------------- /src/FSharpApiSearch/Engine/Matchers/TypeNameEquality.fs: -------------------------------------------------------------------------------- 1 | module internal FSharpApiSearch.TypeNameEquality 2 | 3 | open System 4 | open System.Collections.Generic 5 | open EngineTypes 6 | 7 | type FailureReason = 8 | | DifferentGenericParameter of leftLength:int * rightLength:int 9 | | DifferentName 10 | | DifferentAssemblyName 11 | 12 | type Result = Result 13 | 14 | type TestBuilder() = 15 | member inline __.Bind(x, f) : Result = 16 | match x with 17 | | Ok d1 -> 18 | match f() with 19 | | Ok d2 -> Ok (d1 + d2) 20 | | failure -> failure 21 | | failure -> failure 22 | 23 | member inline __.Zero() : Result = Ok 0 24 | 25 | let test = TestBuilder() 26 | 27 | let testee (x: NameItem) = 28 | match x.Name with 29 | | SymbolName n -> n 30 | | OperatorName (_, n) -> n 31 | | WithCompiledName (n, _) -> n 32 | 33 | let forall2 (f: 'a -> 'b -> Result) (xs: 'a list) (ys: 'b list) : Result = 34 | let distance = ref 0 35 | let rec loop xs ys = 36 | match xs, ys with 37 | | x :: xs, y :: ys -> 38 | match f x y with 39 | | Ok d -> 40 | distance := !distance + d 41 | loop xs ys 42 | | failure -> failure 43 | | _ -> Ok !distance 44 | loop xs ys 45 | 46 | let testGenericParameterCount (x: int) (y: int) = 47 | if x = y then 48 | Ok 0 49 | else 50 | Error (DifferentGenericParameter (x, y)) 51 | 52 | let testStringExact (cmp: StringComparison) (x: string) (y: string) : Result = 53 | if x.Equals(y, cmp) then 54 | Ok 0 55 | else 56 | Error DifferentName 57 | 58 | let testName cmp (xs: Name) (ys: Name) = 59 | let f x y = test { 60 | do! testStringExact cmp (testee x) (testee y) 61 | do! testGenericParameterCount x.GenericParameters.Length y.GenericParameters.Length 62 | } 63 | forall2 f xs ys 64 | 65 | let testAssemblyName (x: ConcreteType) (y: ConcreteType) = 66 | if x.AssemblyName = y.AssemblyName then 67 | Ok 0 68 | else 69 | Error DifferentAssemblyName 70 | 71 | let testConcreteType (x: ConcreteType) (y: ConcreteType) = test { 72 | do! testAssemblyName x y 73 | do! testName StringComparison.InvariantCulture x.Name y.Name 74 | } 75 | 76 | let concreteTypeComparer = 77 | { new IEqualityComparer with 78 | member this.Equals(x, y) = testConcreteType x y = Ok 0 79 | member this.GetHashCode(x) = 80 | let mutable value = x.AssemblyName.GetHashCode() 81 | for item in x.Name do 82 | value <- value ^^^ item.Name.GetHashCode() 83 | value <- value ^^^ item.GenericParameters.Length.GetHashCode() 84 | value 85 | } 86 | 87 | let testStringSubstring (cmp: StringComparison) (userInput: string) (actual: string) = 88 | let index = actual.IndexOf(userInput, cmp) 89 | if index < 0 then 90 | Error DifferentName 91 | else 92 | Ok (actual.Length - userInput.Length) 93 | 94 | let testUserInputAndConcreteType (cmp: StringComparison) (testStr: StringComparison -> string -> string -> Result) (userInput: UserInputType) (actual: ConcreteType) = 95 | let testNameItem (p: NameItem) (f: NameItem) = test { 96 | match p.GenericParameters, f.GenericParameters with 97 | | [], _ -> 98 | do! testStr cmp (testee p) (testee f) 99 | | _ -> 100 | do! testStr cmp (testee p) (testee f) 101 | do! testGenericParameterCount p.GenericParameters.Length f.GenericParameters.Length 102 | } 103 | test { 104 | do! testGenericParameterCount userInput.GenericParameterCount actual.GenericParameterCount 105 | 106 | do! forall2 testNameItem userInput.Name actual.Name 107 | } 108 | 109 | let private sameName' cmp testStr x y = 110 | match x, y with 111 | | ConcreteType left, ConcreteType right -> testConcreteType left right 112 | | ConcreteType concrete, UserInputType userInput 113 | | UserInputType userInput, ConcreteType concrete -> testUserInputAndConcreteType cmp testStr userInput concrete 114 | | UserInputType left, UserInputType right -> 115 | test { 116 | do! testGenericParameterCount left.GenericParameterCount right.GenericParameterCount 117 | do! testName cmp left.Name right.Name 118 | } 119 | 120 | type Equality = Identifier -> Identifier -> Result 121 | 122 | let sameName x y = sameName' StringComparison.InvariantCulture testStringExact x y 123 | let sameNameIgnoreCase x y = sameName' StringComparison.InvariantCultureIgnoreCase testStringExact x y 124 | 125 | let equalityFromOptions opt : Equality = 126 | let comparison = 127 | match opt.IgnoreCase with 128 | | Enabled -> StringComparison.InvariantCultureIgnoreCase 129 | | Disabled -> StringComparison.InvariantCulture 130 | let testStr = 131 | match opt.Substring with 132 | | Enabled -> testStringSubstring 133 | | Disabled -> testStringExact 134 | sameName' comparison testStr -------------------------------------------------------------------------------- /src/FSharpApiSearch/FSharpApiSearch.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | true 6 | FSharpApiSearch 7 | --warnon:1182 8 | 3 9 | false 10 | 11 | 12 | portable 13 | false 14 | 15 | 16 | portable 17 | true 18 | 19 | 20 | true 21 | portable 22 | false 23 | false 24 | TRACE;DEBUG;EngineDebug 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/FSharpApiSearch/FSharpApiSearchClient.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch 2 | 3 | open FSharpApiSearch.AssemblyLoader 4 | open FSharpApiSearch.StringPrinter 5 | open FSharp.Collections.ParallelSeq 6 | 7 | type TargetSummary = { 8 | AssemblyName: string 9 | PublicApiNumber: int 10 | } 11 | 12 | type FSharpApiSearchClient(targets: string seq, database: Database) = 13 | let targetDictionaries = database |> Seq.filter (fun x -> targets |> Seq.exists ((=)x.AssemblyName)) |> Seq.toArray 14 | 15 | static member DefaultTargets = [ 16 | "mscorlib" 17 | "System" 18 | "System.Core" 19 | "FSharp.Core" 20 | ] 21 | 22 | member this.Search(query: string, options: SearchOptions) : Query * seq = Engine.search database options targetDictionaries query 23 | 24 | member this.Sort(results: seq) = 25 | let sortKey (result: Result) = 26 | let kind = 27 | match result.Api.Kind with 28 | | ApiKind.ModuleDefinition -> 0 29 | | ApiKind.TypeDefinition -> 0 30 | | ApiKind.TypeAbbreviation -> 1 31 | | ApiKind.ComputationExpressionBuilder -> 1 32 | | _ -> 2 33 | let distance = result.Distance 34 | let name = FSharp.printApiName result.Api 35 | let type' = FSharp.printAccessPath None result.Api 36 | (kind, distance, name, type') 37 | match results with 38 | | :? pseq as xs -> PSeq.sortBy sortKey xs :> seq 39 | | xs -> Seq.sortBy sortKey xs 40 | 41 | 42 | member this.TargetAssemblies: string list = targetDictionaries |> Array.map (fun x -> x.AssemblyName) |> Array.toList 43 | 44 | member this.Targets: TargetSummary list = targetDictionaries |> Array.map (fun x -> { AssemblyName = x.AssemblyName; PublicApiNumber = x.PublicApiNumber }) |> Array.toList -------------------------------------------------------------------------------- /src/FSharpApiSearch/Misc.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch 2 | 3 | type Lens<'a, 'b> = { 4 | Get: 'a -> 'b 5 | Set: 'b -> 'a -> 'a 6 | } 7 | 8 | [] 9 | module internal OptionModule = 10 | type OptionBuilder() = 11 | member inline this.Bind(x, f) = Option.bind f x 12 | member inline this.Return(x) = Some x 13 | member inline this.ReturnFrom(x) = x 14 | 15 | let option = OptionBuilder() 16 | 17 | module internal Seq = 18 | let foldOptionMapping f xs = 19 | xs 20 | |> Seq.fold (fun acc x -> 21 | option { 22 | let! acc = acc 23 | let! result = f x 24 | return result :: acc 25 | } 26 | ) (Some []) 27 | |> Option.map Seq.rev 28 | 29 | [] 30 | module internal Extensions = 31 | open System.Text 32 | type StringBuilder with 33 | member this.Append(print: StringBuilder -> StringBuilder) = print this 34 | member this.AppendJoin(sep: string, xs: 'a seq, print: 'a -> StringBuilder -> StringBuilder) : StringBuilder = 35 | if Seq.isEmpty xs then 36 | this 37 | else 38 | let first = ref true 39 | 40 | for x in xs do 41 | if !first then 42 | this.Append(print x) |> ignore 43 | first := false 44 | else 45 | this.Append(sep).Append(print x) |> ignore 46 | this 47 | 48 | member this.AppendJoin(sep: string, xs: string seq) = this.AppendJoin(sep, xs, (fun x sb -> sb.Append(x))) 49 | 50 | module internal IDictionary = 51 | open System.Collections.Generic 52 | let empty<'k, 'v when 'k : equality> = dict (Seq.empty<'k * 'v>) 53 | 54 | module internal Map = 55 | let ofList2 (keys: 'k list) (values: 'v list) = 56 | let rec loop keys values map = 57 | match keys, values with 58 | | key :: keys, value :: values -> loop keys values (Map.add key value map) 59 | | [], [] -> map 60 | | _ -> failwith "invalid length" 61 | loop keys values Map.empty -------------------------------------------------------------------------------- /src/FSharpApiSearch/Print/HtmlPrintHelper.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.HtmlPrintHelper 2 | 3 | open System.Text 4 | open System.Collections.Generic 5 | open System 6 | 7 | type ColorId = int 8 | 9 | type StructuredResult = { 10 | Text: (string * ColorId option)[] 11 | AllText: string 12 | } 13 | 14 | type private Context = { 15 | BeginIndex: int 16 | EndIndex: int 17 | ColorId: ColorId option 18 | } 19 | 20 | module private Extensions = 21 | type System.Collections.Generic.List<'t> with 22 | member inline this.Last = this.[this.Count - 1] 23 | member inline this.IsEmpty = this.Count = 0 24 | 25 | type System.Collections.Generic.Stack<'t> with 26 | member inline this.TryPeek = 27 | if this.Count = 0 then 28 | None 29 | else 30 | Some (this.Peek()) 31 | member inline this.IsEmpty = this.Count = 0 32 | 33 | open Extensions 34 | 35 | type StructuredWriter() = 36 | let sb = StringBuilder() 37 | let results = ResizeArray() 38 | let stack = Stack() 39 | 40 | let add beginIndex endIndex color = 41 | if beginIndex > endIndex then 42 | () 43 | else 44 | results.Add({ BeginIndex = beginIndex; EndIndex = endIndex; ColorId = color }) 45 | 46 | member private this.Push() = 47 | let beginIndex = 48 | if results.IsEmpty then 49 | 0 50 | else 51 | results.Last.EndIndex + 1 52 | let endIndex = sb.Length - 1 53 | let color = stack.TryPeek 54 | 55 | add beginIndex endIndex color 56 | 57 | member this.BeginColor(color: ColorId) = 58 | this.Push() 59 | stack.Push(color) 60 | 61 | member this.EndColor(color: ColorId) = 62 | this.Push() 63 | let popped = stack.Pop() 64 | assert (color = popped) 65 | () 66 | 67 | member this.Result : StructuredResult = 68 | assert (stack.IsEmpty) 69 | this.Push() 70 | { 71 | Text = results.ToArray() |> Array.map (fun c -> sb.ToString(c.BeginIndex, c.EndIndex - c.BeginIndex + 1), c.ColorId) 72 | AllText = sb.ToString() 73 | } 74 | 75 | member this.Write(str: string) = sb.Append(str) |> ignore 76 | 77 | interface Writer with 78 | member this.Write(str: string) = this.Write(str) 79 | member this.WriteLine(str: string) = sb.AppendLine(str) |> ignore 80 | member this.WriteLine() = sb.AppendLine() |> ignore 81 | 82 | type Handler() = 83 | interface SignaturePrinterHandler with 84 | member this.BeginPrintType(writer, _, queryId) = queryId |> Option.iter (fun q -> writer.BeginColor(q.Id)) 85 | member this.EndPrintType(writer, _, queryId) = queryId |> Option.iter (fun q -> writer.EndColor(q.Id)) 86 | member this.BeginPrintSyntax(writer, _, queryId) = queryId |> Option.iter (fun q -> writer.BeginColor(q.Id)) 87 | member this.EndPrintSyntax(writer, _, queryId) = queryId |> Option.iter (fun q -> writer.EndColor(q.Id)) 88 | 89 | interface QueryPrinterHandler with 90 | member this.BeginPrintArea(writer, queryId) = writer.BeginColor(queryId.Id) 91 | member this.EndPrintArea(writer, queryId) = writer.EndColor(queryId.Id) 92 | 93 | let signature (result: Result) (print: SignaturePrinter<_> -> SignaturePrinter<_>) = 94 | let writer = StructuredWriter() 95 | let printer = SignaturePrinter<_>(writer, Handler(), result) 96 | print printer |> ignore 97 | writer.Result 98 | 99 | let query (print: QueryPrinter<_> -> QueryPrinter<_>) = 100 | let writer = StructuredWriter() 101 | let printer = QueryPrinter<_>(writer, Handler()) 102 | print printer |> ignore 103 | writer.Result -------------------------------------------------------------------------------- /src/FSharpApiSearch/Print/PrintTypes.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch 2 | 3 | open System 4 | open System.IO 5 | 6 | type Writer = 7 | abstract Write : string -> unit 8 | abstract WriteLine : string -> unit 9 | abstract WriteLine : unit -> unit 10 | 11 | module Writer = 12 | let wrap (w: #System.IO.TextWriter) = 13 | { new Writer with 14 | member this.Write(str: string) = w.Write(str) 15 | member this.WriteLine(str: string) = w.WriteLine(str) 16 | member this.WriteLine() = w.WriteLine() 17 | } 18 | 19 | type SignaturePrinterHandler<'Writer> = 20 | abstract BeginPrintType : 'Writer * LowType * QueryId option -> unit 21 | abstract EndPrintType : 'Writer * LowType * QueryId option -> unit 22 | 23 | abstract BeginPrintSyntax : 'Writer * string * QueryId option -> unit 24 | abstract EndPrintSyntax : 'Writer * string * QueryId option -> unit 25 | 26 | module SignaturePrinterHandler = 27 | let empty<'w> = 28 | { new SignaturePrinterHandler<'w> with 29 | member this.BeginPrintType(_, _, _) = () 30 | member this.EndPrintType(_, _, _) = () 31 | member this.BeginPrintSyntax(_, _, _) = () 32 | member this.EndPrintSyntax(_, _, _) = () 33 | } 34 | 35 | type SignaturePrinter<'Writer when 'Writer :> Writer> internal (writer: 'Writer, handler: SignaturePrinterHandler<'Writer>, positions: Map) = 36 | new (writer, handler, result: Result) = new SignaturePrinter<_>(writer, handler, result.MatchPositions) 37 | new (writer, handler) = new SignaturePrinter<_>(writer, handler, Map.empty) 38 | 39 | member this.Write(str: string) : unit = writer.Write(str) 40 | member this.Write(print: SignaturePrinter<_> -> SignaturePrinter<_>) : unit = print this |> ignore 41 | member this.WriteLine() : unit = writer.WriteLine() 42 | member this.WriteLine(str: string) : unit = writer.WriteLine(str) 43 | member this.WriteLine(print: SignaturePrinter<_> -> SignaturePrinter<_>) : unit = print this |> ignore; writer.WriteLine() 44 | 45 | member this.Append(str: string) : SignaturePrinter<_> = writer.Write(str); this 46 | member this.Append(print: SignaturePrinter<_> -> SignaturePrinter<_>) : SignaturePrinter<_> = print this 47 | member this.AppendJoin(sep: string, xs: seq<_>, print: _ -> SignaturePrinter<_> -> SignaturePrinter<_>) : SignaturePrinter<_> = 48 | let mutable first = true 49 | for x in xs do 50 | if not first then 51 | this.Append(sep) |> ignore 52 | else 53 | first <- false 54 | this.Append(print x) |> ignore 55 | this 56 | member this.AppendJoin(sep: string, xs: seq<_>) : SignaturePrinter<_> = this.AppendJoin(sep, xs, (fun x p -> p.Append(x))) 57 | member this.BeginPrintType(t: LowType) : SignaturePrinter<_> = 58 | match t.Position with 59 | | AtQuery (Some pos, _) -> handler.BeginPrintType(writer, t, Some pos) 60 | | AtSignature pos -> handler.BeginPrintType(writer, t, positions.TryFind(pos)) 61 | | AtQuery (None, _) | Unknown -> handler.BeginPrintType(writer, t, None) 62 | this 63 | member this.EndPrintType(t: LowType) : SignaturePrinter<_> = 64 | match t.Position with 65 | | AtQuery (Some pos, _) -> handler.EndPrintType(writer, t, Some pos) 66 | | AtSignature pos -> handler.EndPrintType(writer, t, positions.TryFind(pos)) 67 | | AtQuery (None, _) | Unknown -> handler.EndPrintType(writer, t, None) 68 | this 69 | member this.BeginPrintSyntax(syntax: ComputationExpressionSyntax) : SignaturePrinter<_> = 70 | match syntax.Position with 71 | | AtQuery (Some pos, _) -> handler.BeginPrintSyntax(writer, syntax.Syntax, Some pos) 72 | | AtSignature pos -> handler.BeginPrintSyntax(writer, syntax.Syntax, positions.TryFind(pos)) 73 | | AtQuery (None, _) | Unknown -> handler.BeginPrintSyntax(writer, syntax.Syntax, None) 74 | this 75 | member this.EndPrintSyntax(syntax: ComputationExpressionSyntax) : SignaturePrinter<_> = 76 | match syntax.Position with 77 | | AtQuery (Some pos, _) -> handler.EndPrintSyntax(writer, syntax.Syntax, Some pos) 78 | | AtSignature pos -> handler.EndPrintSyntax(writer, syntax.Syntax, positions.TryFind(pos)) 79 | | AtQuery (None, _) | Unknown -> handler.EndPrintSyntax(writer, syntax.Syntax, None) 80 | this 81 | 82 | type QueryPrinterHandler<'Writer when 'Writer :> Writer> = 83 | abstract BeginPrintArea : 'Writer * QueryId -> unit 84 | abstract EndPrintArea : 'Writer * QueryId -> unit 85 | 86 | module QueryPrinterHandler = 87 | let empty<'Writer when 'Writer :> Writer> = 88 | { new QueryPrinterHandler<'Writer> with 89 | member this.BeginPrintArea(_, _) = () 90 | member this.EndPrintArea(_, _) = () 91 | } 92 | 93 | type QueryPrinter<'Writer when 'Writer :> Writer>(writer: 'Writer, handler: QueryPrinterHandler<'Writer>) = 94 | new (writer) = QueryPrinter<_>(writer, QueryPrinterHandler.empty) 95 | 96 | member this.Write(str: string) = writer.Write(str) 97 | member this.WriteLine(str: string) = writer.WriteLine(str) 98 | member this.WriteLine() = writer.WriteLine() 99 | 100 | member this.BeginPrintType(id: QueryId) = handler.BeginPrintArea(writer, id) 101 | member this.EndPrintType(id: QueryId) = handler.EndPrintArea(writer, id) -------------------------------------------------------------------------------- /src/FSharpApiSearch/Print/Printer.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.Printer 2 | 3 | module FSharp = 4 | let printFullName (api: Api) (p: SignaturePrinter<_>) = p.Append(FSharpFormat.printName_full (ApiName.toName api.Name)) 5 | let printApiName (api: Api) (p: SignaturePrinter<_>) = p.Append(FSharpFormat.printApiName (ApiName.toName api.Name)) 6 | let printAccessPath (depth: int option) (api: Api) (p: SignaturePrinter<_>) = p.Append(FSharpFormat.printAccessPath depth (ApiName.toName api.Name)) 7 | 8 | let printSignature (api:Api) (p: SignaturePrinter<_>) = p.Append(FSharpFormat.printApiSignature false api.Signature) 9 | let printKind (api: Api) (p: SignaturePrinter<_>) = p.Append(FSharpFormat.printApiKind api.Kind) 10 | 11 | let hasTypeConstraints (api: Api) = not api.TypeConstraints.IsEmpty 12 | let printTypeConstraints (api: Api) (p: SignaturePrinter<_>) = 13 | p.Append("when ") 14 | .AppendJoin(" and ", api.TypeConstraints, FSharpFormat.printConstraint false) 15 | 16 | 17 | module CSharp = 18 | let printFullName (api: Api) (p: SignaturePrinter<_>) = p.Append(CSharpFormat.printName_full (ApiName.toName api.Name)) 19 | let printApiName (api: Api) (p: SignaturePrinter<_>) = p.Append(CSharpFormat.printApiName (ApiName.toName api.Name)) 20 | let printAccessPath (depth: int option) (api: Api) (p: SignaturePrinter<_>) = p.Append(CSharpFormat.printAccessPath depth (ApiName.toName api.Name)) 21 | 22 | let printSignature (api:Api) (p: SignaturePrinter<_>) = p.Append(CSharpFormat.printApiSignature api.Signature) 23 | let printKind (api: Api) (p: SignaturePrinter<_>) = p.Append(CSharpFormat.printApiKind api.Kind) 24 | 25 | let hasTypeConstraints (api: Api) = api.TypeConstraints |> List.exists CSharpFormat.csharpTypeConstraintPred 26 | let printTypeConstraints (api: Api) (p: SignaturePrinter<_>) = 27 | p.Append(CSharpFormat.printConstraints api.TypeConstraints) -------------------------------------------------------------------------------- /src/FSharpApiSearch/Print/QueryPrinter.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.QueryPrinter 2 | 3 | module internal Impl = 4 | let collectPosition (result: ResizeArray<_>) (x: LowType) = 5 | let add x = result.Add(x) 6 | let rec f = function 7 | | Wildcard (_, p) -> add p 8 | | Variable (_, _, p) -> add p 9 | | Identifier (_, p) -> add p 10 | | Arrow ((ps, ret), p) -> List.iter f ps; f ret; add p 11 | | Tuple ({ Elements = xs }, p) -> List.iter f xs; add p 12 | | Generic (id, args, p) -> f id; List.iter f args; add p 13 | | ByRef (_, t, p) -> f t; add p 14 | | Subtype (t, p) -> f t; add p 15 | | Choice (o, xs, p) -> f o; List.iter f xs; add p 16 | | TypeAbbreviation _ | Delegate _ -> () 17 | | LoadingType _ -> Name.loadingNameError() 18 | f x 19 | 20 | let collectQueryId (query: Query) = 21 | let result = ResizeArray<_>() 22 | let collect result = function 23 | | SignatureQuery.Signature s -> collectPosition result s 24 | | SignatureQuery.Wildcard _ -> () 25 | match query.Method with 26 | | QueryMethod.ByName (_, q) -> collect result q 27 | | QueryMethod.BySignature q -> collect result q 28 | | QueryMethod.ByNameOrSignature (_, q) -> collect result q 29 | | QueryMethod.ByActivePattern q -> 30 | match q.Signature with 31 | | ActivePatternSignature.AnyParameter (a, b) -> collectPosition result a; collectPosition result b 32 | | ActivePatternSignature.Specified t -> collectPosition result t 33 | | QueryMethod.ByComputationExpression q -> q.Syntaxes |> List.iter (fun s -> result.Add(s.Position)) 34 | 35 | result.ToArray() 36 | 37 | let rangeToPrint (ps: Position[]) = 38 | ps 39 | |> Array.choose (function 40 | | AtQuery (Some id, range) -> Some (id, range) 41 | | AtQuery (None, _) -> None 42 | | AtSignature _ -> None 43 | | Unknown _ -> None 44 | ) 45 | |> Array.groupBy (fun (id, _) -> id) 46 | |> Array.map (fun (id, values) -> 47 | let range = { 48 | Begin = values |> Array.map (fun (_, range) -> range.Begin) |> Array.min 49 | End = values |> Array.map (fun (_, range) -> range.End) |> Array.max 50 | } 51 | (id, range) 52 | ) 53 | |> Array.sortBy (fun (id, _) -> id) 54 | 55 | let split (query: string) (ranges: (QueryId * QueryRange)[]) : (string * QueryId option)[] = 56 | let result = ResizeArray() 57 | let mutable index = 0 58 | 59 | for (queryId, range) in ranges do 60 | if index <> range.Begin then 61 | result.Add(query.[index..(range.Begin - 1)], None) 62 | 63 | result.Add(query.[range.Begin..(range.End - 1)], Some queryId) 64 | index <- range.End 65 | 66 | if index < query.Length then 67 | result.Add(query.[index..(query.Length - 1)], None) 68 | 69 | result.ToArray() 70 | 71 | open Impl 72 | 73 | let print (query: Query) (printer: QueryPrinter<_>) = 74 | collectQueryId query 75 | |> rangeToPrint 76 | |> split query.OriginalString 77 | |> Array.iter (fun (str, queryId) -> 78 | match queryId with 79 | | Some id -> 80 | printer.BeginPrintType(id) 81 | printer.Write(str) 82 | printer.EndPrintType(id) 83 | | None -> 84 | printer.Write(str) 85 | ) 86 | printer -------------------------------------------------------------------------------- /src/FSharpApiSearch/Print/StringPrinter.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.StringPrinter 2 | 3 | open System.IO 4 | open System.Text 5 | open System.Runtime.CompilerServices 6 | 7 | let internal printStringBuilder (sb: StringBuilder) (print: SignaturePrinter<_> -> SignaturePrinter<_>) = 8 | use writer = new StringWriter(sb) 9 | let p = SignaturePrinter(Writer.wrap writer, SignaturePrinterHandler.empty) 10 | print p |> ignore 11 | sb 12 | 13 | let internal printString (print: SignaturePrinter<_> -> SignaturePrinter<_>) = 14 | let sb = StringBuilder() 15 | printStringBuilder sb print |> ignore 16 | sb.ToString() 17 | 18 | module FSharp = 19 | let printFullName (api: Api) = Printer.FSharp.printFullName api |> printString 20 | let printApiName (api: Api) = Printer.FSharp.printApiName api |>printString 21 | let printAccessPath (depth: int option) (api: Api) = Printer.FSharp.printAccessPath depth api |> printString 22 | let printSignature (api:Api) = Printer.FSharp.printSignature api |> printString 23 | let printKind (api: Api) = Printer.FSharp.printKind api |> printString 24 | let printTypeConstraints (api: Api) = Printer.FSharp.printTypeConstraints api |> printString 25 | let tryPrintTypeConstraints (api: Api) = 26 | if Printer.FSharp.hasTypeConstraints api then 27 | Some (printTypeConstraints api) 28 | else 29 | None 30 | 31 | module CSharp = 32 | let printFullName (api: Api) = Printer.CSharp.printFullName api |> printString 33 | let printApiName (api: Api) = Printer.CSharp.printApiName api |> printString 34 | let printAccessPath (depth: int option) (api: Api) = Printer.CSharp.printAccessPath depth api |> printString 35 | let printSignature (api:Api) = Printer.CSharp.printSignature api |> printString 36 | let printKind (api: Api) = Printer.CSharp.printKind api |> printString 37 | let printTypeConstraints (api: Api) = Printer.CSharp.printTypeConstraints api |> printString 38 | let tryPrintTypeConstraints (api: Api) = 39 | if Printer.CSharp.hasTypeConstraints api then 40 | Some (printTypeConstraints api) 41 | else 42 | None 43 | 44 | type TypeVariable with 45 | member this.Print(sb: StringBuilder) = printStringBuilder sb (FSharpFormat.printTypeVariable false VariableSource.Target this) 46 | member this.Print() = printString (FSharpFormat.printTypeVariable false VariableSource.Target this) 47 | 48 | type NameItem with 49 | member this.Print() = printString (FSharpFormat.printNameItem this) 50 | 51 | type ApiName with 52 | member this.Print() = printString (FSharpFormat.printName_full (ApiName.toName this)) 53 | 54 | type LowType with 55 | member this.Print() = printString (FSharpFormat.printLowType_short false this) 56 | member internal this.Debug() = printString (FSharpFormat.printLowType_short true this) 57 | 58 | type ApiSignature with 59 | member this.Print() = printString (FSharpFormat.printApiSignature false this) 60 | member internal this.Debug() = printString (FSharpFormat.printApiSignature true this) 61 | 62 | type TypeConstraint with 63 | member this.Print() = printString (FSharpFormat.printConstraint false this) 64 | member internal this.Debug() = printString (FSharpFormat.printConstraint true this) 65 | 66 | type FullTypeDefinition with 67 | member this.Print() = printString (FSharpFormat.printFullTypeDefinition false this) 68 | member internal this.Debug() = printString (FSharpFormat.printFullTypeDefinition true this) 69 | 70 | module internal LowType = 71 | let debug (x: LowType) = x.Debug() 72 | 73 | module internal ApiSignature = 74 | let debug (x: ApiSignature) = x.Debug() 75 | let print (x: ApiSignature) = x.Print() 76 | 77 | module internal TypeConstraint = 78 | let debug (x: TypeConstraint) = x.Debug() 79 | 80 | module internal FullTypeDefinition = 81 | let debug (x: FullTypeDefinition) = x.Debug() 82 | 83 | [] 84 | type internal Extensions() = 85 | [] 86 | static member Print(name: Name) = printString (FSharpFormat.printName_full name) -------------------------------------------------------------------------------- /src/FSharpApiSearch/paket.references: -------------------------------------------------------------------------------- 1 | group Core 2 | FSharp.Core 3 | FParsec 4 | FSharp.Compiler.Service 5 | FSharp.Collections.ParallelSeq 6 | MessagePack 7 | MessagePack.FSharpExtensions 8 | System.Reflection.Metadata -------------------------------------------------------------------------------- /src/FSharpApiSearch/paket.template: -------------------------------------------------------------------------------- 1 | type project 2 | owners 3 | hafuu 4 | authors 5 | hafuu 6 | projectUrl 7 | http://github.com/hafuu/FSharpApiSearch 8 | licenseUrl 9 | http://github.com/hafuu/FSharpApiSearch/blob/master/LICENSE.txt 10 | requireLicenseAcceptance 11 | false 12 | tags 13 | F# fsharp api search 14 | summary 15 | F# API search engine 16 | description 17 | F# API search engine 18 | dependencies 19 | FSharp.Core >= LOCKEDVERSION-Core 20 | FParsec >= LOCKEDVERSION-Core 21 | FSharp.Compiler.Service >= LOCKEDVERSION-Core 22 | FSharp.Collections.ParallelSeq >= LOCKEDVERSION-Core 23 | MessagePack >= LOCKEDVERSION-Core 24 | MessagePack.FSharpExtensions >= LOCKEDVERSION-Core 25 | System.Reflection.Metadata >= LOCKEDVERSION-Core -------------------------------------------------------------------------------- /src/FSharpApiSearch/prim-types-members.fsx: -------------------------------------------------------------------------------- 1 | open System 2 | open System.IO 3 | open System.Text.RegularExpressions 4 | 5 | let primitiveTypes = 6 | Map.ofList [ 7 | "bool", "Boolean" 8 | "byte", "Byte" 9 | "char", "Char" 10 | "decimal", "Decimal" 11 | "float", "Double" 12 | "float32", "Single" 13 | "int16", "Int16" 14 | "int", "Int32" 15 | "int32", "Int32" 16 | "int64", "Int64" 17 | "nativeint", "IntPtr" 18 | "sbyte", "SByte" 19 | "string", "String" 20 | "uint16", "UInt16" 21 | "uint32", "UInt32" 22 | "uint64", "UInt64" 23 | "unativeint", "UIntPtr" 24 | ] 25 | 26 | let file = 27 | File.ReadAllLines(fsi.CommandLineArgs.[1]) 28 | 29 | let nameAndSig (line: string) = 30 | let m = Regex.Match(line, @"\(static member ([^:]+):\s+([^)]+)\)") 31 | let name = m.Groups.[1].Value.Trim() 32 | let sig' = m.Groups.[2].Value.Trim() 33 | name, sig' 34 | 35 | let readType (line: string) = 36 | let m = Regex.Match(line, @"when \^\w+ : (\w+) ") 37 | if m.Success then 38 | Some (m.Groups.[1].Value.Trim()) 39 | else 40 | None 41 | 42 | let rec back index = 43 | if file.[index].Contains("let") then 44 | index + 1 45 | else 46 | back (index - 1) 47 | 48 | let rec forward index = 49 | if file.[index].Contains("let") then 50 | index - 1 51 | else 52 | forward (index + 1) 53 | 54 | file 55 | |> Array.indexed 56 | |> Array.filter (fun (_, line) -> Regex.IsMatch(line, @"\(static member") && (Regex.IsMatch(line, @"^\s+let") = false)) 57 | |> Array.collect (fun (i, line) -> 58 | let types = 59 | file.[(back i)..(forward i)] 60 | |> Array.choose readType 61 | 62 | let name, sig' = nameAndSig line 63 | types |> Array.map (fun t -> t, name, sig') 64 | ) 65 | |> Array.groupBy (fun (t, _, _) -> t) 66 | |> Array.sort 67 | |> Array.iter (fun (t, members) -> 68 | let getName key = Map.find key primitiveTypes 69 | let typeName = getName t 70 | let members = 71 | members 72 | |> Array.distinct 73 | |> Array.sort 74 | |> Array.map (fun (_, memberName, sig') -> 75 | let memberName = 76 | if memberName.StartsWith("(") then 77 | sprintf "PrettyNaming.CompileOpName(\"%s\")" (memberName.Replace("(", "").Replace(")", "")) 78 | else 79 | sprintf "\"%s\"" memberName 80 | let parameters, ret = 81 | let sig' = Regex.Replace(sig', @"['\^]\w+", t) 82 | let xs = sig'.Split([| "->" |], StringSplitOptions.None) |> Array.map (fun x -> x.Trim()) 83 | let args = Array.truncate (Array.length xs - 1) xs |> Array.toList 84 | let ret = Array.last xs 85 | (args, getName ret) 86 | let kind = 87 | match parameters with 88 | | [] -> "MemberKind.Property PropertyKind.Get" 89 | | _ -> "MemberKind.Method" 90 | let parameters = 91 | parameters 92 | |> List.collect (fun x -> x.Split('*') |> Array.toList) 93 | |> List.map (fun x -> x.Trim()) 94 | |> List.map (fun x -> sprintf "Parameter.%s" (getName x)) 95 | |> function 96 | | [] -> "" 97 | | xs -> String.concat "; " xs |> sprintf "[ %s ]" 98 | |> sprintf "[ %s ]" 99 | sprintf """ { Name = %s; Kind = %s; GenericParameters = []; Parameters = %s; ReturnParameter = Parameter.%s }""" memberName kind parameters ret 100 | ) 101 | |> String.concat "\r\n" 102 | printfn " (TypeInfo.%s, " typeName 103 | printfn """ { 104 | InstanceMembers = [] 105 | StaticMembers = 106 | [ 107 | %s 108 | ] 109 | })""" members 110 | ) 111 | 112 | Console.WriteLine("-----------------") 113 | 114 | primitiveTypes 115 | |> Map.toList 116 | |> List.map snd 117 | |> List.distinct 118 | |> List.iter (fun t -> printfn "let %s = ofDotNetType typeof<%s>" t t) -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/ByRef.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class ByRef 10 | { 11 | public static ref int F(ref int a, out string b) 12 | { 13 | b = ""; 14 | return ref a; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/CSharpLoadTestAssembly.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | CSharpLoadTestAssembly 6 | CSharpLoadTestAssembly 7 | Copyright © 2016 8 | true 9 | $(NoWarn);1591 10 | 11 | 12 | portable 13 | 14 | 15 | portable 16 | 17 | 18 | true 19 | DEBUG;TRACE 20 | portable 21 | MinimumRecommendedRules.ruleset 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/Class.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class StaticMemberClass 10 | { 11 | public StaticMemberClass() { } 12 | 13 | public StaticMemberClass(string x, string y) { } 14 | 15 | public static int[] ArrayMethod() => null; 16 | public static int[,] Array2dMethod() => null; 17 | public static int[,][] NestedArrayMethod() => new[,] { { new int[0], new int[0] } }; 18 | 19 | public static int NoParameterMethod() => 3; 20 | public static void NonCurriedMethod(int x, string y) { } 21 | public static void TupleMethod(Tuple x) { } 22 | 23 | public static int OverloadMethod(int x) => x; 24 | public static string OverloadMethod(string x) => x; 25 | 26 | public static string Getter { get; } 27 | public static string Setter { set { } } 28 | public static string GetterSetter { get; set; } 29 | 30 | public static int Field; 31 | } 32 | 33 | public class InstanceMemberClass 34 | { 35 | public int NoParameterMethod() => 3; 36 | public void NonCurriedMethod(int x, string y) { } 37 | public void TupleMethod(Tuple x) { } 38 | 39 | public int OverloadMethod(int x) => x; 40 | public string OverloadMethod(string x) => x; 41 | 42 | public string Getter { get; } 43 | public string Setter { set { } } 44 | public string GetterSetter { get; set; } 45 | 46 | public int Field; 47 | 48 | protected string ProtectedMethod() => ""; 49 | } 50 | 51 | public class IndexedGetter 52 | { 53 | public int this[int x] { get { return x; } } 54 | } 55 | 56 | public class IndexedSetter 57 | { 58 | public int this[int x] { set { } } 59 | } 60 | 61 | public class IndexedGetterSetter 62 | { 63 | public int this[int x] { get { return x; } set { } } 64 | } 65 | 66 | public struct Struct 67 | { 68 | public int Field; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/Delegate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public delegate void TestDelegate(string x); 10 | } 11 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/ExtensionMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public static class ExtensionMember 10 | { 11 | public static void Extension(this int x) { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/Interface.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public interface Interface 10 | { 11 | int Method(int x, string y); 12 | int Property { get; set; } 13 | } 14 | 15 | public interface GenericInterface 16 | { 17 | int Method(T x); 18 | T Property { set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/NestedClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class OuterClass 10 | { 11 | public OuterClass(){ } 12 | 13 | public class InnerClass 14 | { 15 | public InnerClass() { } 16 | public static int StaticMethod() => 3; 17 | } 18 | } 19 | 20 | public class GenericOuterClass 21 | { 22 | public GenericOuterClass() { } 23 | 24 | public class GenericInnerClass 25 | { 26 | public GenericInnerClass() { } 27 | 28 | public static void Method(T x, U y) { } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/Operators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class Operators 10 | { 11 | public static Operators operator+ (Operators x, Operators y) => x; 12 | public static implicit operator Operators (string x) => new Operators(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/OptinalParameters.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.FSharp.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CSharpLoadTestAssembly 9 | { 10 | public class OptinalParameters 11 | { 12 | public static void F(int x = 0) { } 13 | public static void G(FSharpOption x = null) { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/ParamArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class ParamArray 10 | { 11 | public void F(params int[] xs) { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから 6 | // 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 7 | // その型の ComVisible 属性を true に設定してください。 8 | [assembly: ComVisible(false)] 9 | 10 | // このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります 11 | [assembly: Guid("6273542c-01f5-4ebf-8aab-9fcaa96bea62")] 12 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/Tuples.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class Tuples 10 | { 11 | public static Tuple F(Tuple x) => Tuple.Create(1, "a"); 12 | public static (int, string) G((int, string) x) => (1, "a"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/TypeConstraints.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CSharpLoadTestAssembly 8 | { 9 | public class TypeConstraints 10 | { 11 | public static void Struct(T x) where T : struct { } 12 | public static void Class(T x) where T : class { } 13 | public static void New(T x) where T : new() { } 14 | public static void Subtype(T x) where T : IComparable { } 15 | public static void VariableSubtype(T x, U y) where T : U { } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/CSharpLoadTestAssembly/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | System.ValueTuple 3 | FSharp.Core 4 | -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/ComputationExpressionMatcherTest.fs: -------------------------------------------------------------------------------- 1 | module ComputationExpressionMatcherTest 2 | 3 | open Persimmon 4 | open Persimmon.Syntax.UseTestNameByReflection 5 | open Persimmon.MuscleAssert 6 | open FSharpApiSearch 7 | open TestHelper 8 | open TestHelper.DSL 9 | 10 | let testComputationExpression = parameterize { 11 | source [ 12 | "{ _ } : option<'a>", 1, 2 13 | "{ let! } : option<'a>", 1, 2 14 | "{ let!; return } : option<'a>", 1, 2 15 | "{ for } : option<'a>", 0, 0 16 | "{ _ } : list<'a>", 0, 0 17 | "{ try/finally } : TryFinallyTest", 2, 2 18 | ] 19 | run (fun (query, builderExpected, expected) -> test { 20 | let! apiDict = TestAssemblies.fsharpAssemblyApi 21 | let! dictionaries = TestAssemblies.database 22 | let options = TestHelper.defaultTestOptions 23 | let actual = Engine.search dictionaries options [| apiDict |] query |> snd |> Seq.cache 24 | let computationBuilderCount = actual |> Seq.filter (fun result -> result.Api.Kind = ApiKind.ComputationExpressionBuilder) |> Seq.length 25 | let apiCount = actual |> Seq.filter (fun result -> result.Api.Kind <> ApiKind.ComputationExpressionBuilder) |> Seq.length 26 | do! apiCount |> assertEquals expected 27 | do! computationBuilderCount |> assertEquals builderExpected 28 | }) 29 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/DatabaseTest.fs: -------------------------------------------------------------------------------- 1 | module DatabaseTest 2 | 3 | open Persimmon 4 | open Persimmon.Syntax.UseTestNameByReflection 5 | open FSharpApiSearch 6 | 7 | [] 8 | module CompactTest = 9 | open TestHelper.DSL 10 | 11 | let testRemoveUnusedAssembly = 12 | let t1 = createType "t1" [] |> updateAssembly "lib1" 13 | let t2 = createType "t2" [] |> updateAssembly "lib2" 14 | let t3 = createType "t3" [] |> updateAssembly "lib2_1" 15 | let t4 = createType "t4" [] |> updateAssembly "lib2_1_1" 16 | let lib1 = { 17 | AssemblyName = "lib1" 18 | Api = 19 | [| 20 | { Name = ApiName.ofString "test"; Signature = moduleValue t1; TypeConstraints = []; Document = None } 21 | |] 22 | TypeDefinitions = IDictionary.empty 23 | TypeAbbreviations = [||] 24 | } 25 | let lib2 = { 26 | AssemblyName = "lib2" 27 | Api = 28 | [| 29 | { Name = ApiName.ofString "test"; Signature = moduleFunction' [ [ ptype t2 ]; [ ptype t3 ] ]; TypeConstraints = []; Document = None } 30 | |] 31 | TypeDefinitions = IDictionary.empty 32 | TypeAbbreviations = [||] 33 | } 34 | let lib2_1 = { 35 | AssemblyName = "lib2_1" 36 | Api = 37 | [| 38 | { Name = ApiName.ofString "test"; Signature = moduleFunction' [ [ ptype t3 ]; [ ptype t4 ] ]; TypeConstraints = []; Document = None } 39 | |] 40 | TypeDefinitions = IDictionary.empty 41 | TypeAbbreviations = [||] 42 | } 43 | let lib2_1_1 = { 44 | AssemblyName = "lib2_1_1" 45 | Api = [||] 46 | TypeDefinitions = IDictionary.empty 47 | TypeAbbreviations = [||] 48 | } 49 | let lib3 = { 50 | AssemblyName = "lib3" 51 | Api = [||] 52 | TypeDefinitions = IDictionary.empty 53 | TypeAbbreviations = [||] 54 | } 55 | let database = [| lib1; lib2; lib2_1; lib2_1_1; lib3 |] 56 | parameterize { 57 | source [ 58 | [ "lib1" ], [ "lib1" ] 59 | [ "lib2" ], [ "lib2"; "lib2_1"; "lib2_1_1" ] 60 | [ "lib2_1" ], [ "lib2_1"; "lib2_1_1" ] 61 | [ "lib2_1_1" ], [ "lib2_1_1" ] 62 | [ "lib1"; "lib2" ], [ "lib1"; "lib2"; "lib2_1"; "lib2_1_1" ] 63 | ] 64 | run (fun (mainAssemblies, expected) -> test { 65 | let actual = Database.CompactImpl.removeUnusedAssembly (Set.ofList mainAssemblies) database |> Array.map (fun x -> x.AssemblyName) |> Set 66 | let expected = Set.ofList expected 67 | do! actual |> assertEquals expected 68 | }) 69 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/FSharpApiSearch.Tests.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | FSharpApiSearch.Tests 6 | true 7 | true 8 | 3 9 | Exe 10 | 11 | 12 | portable 13 | false 14 | Project 15 | 16 | 17 | portable 18 | true 19 | 20 | 21 | true 22 | portable 23 | false 24 | false 25 | DEBUG;TRACE 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/FSharpApiSearchClientTest.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearchClientTest 2 | 3 | open Persimmon 4 | open Persimmon.Syntax.UseTestNameByReflection 5 | open Persimmon.MuscleAssert 6 | open System.IO 7 | open FSharpApiSearch 8 | open FSharpApiSearch.StringPrinter 9 | open System.Reflection 10 | 11 | let assemblyName = @"SearchTestAssembly" 12 | let assemblyPath = 13 | Path.Combine( 14 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 15 | , assemblyName + ".dll") 16 | 17 | let testClient = test { 18 | let assemblies = AssemblyLoader.load (TestAssemblies.assemblyResolver.ResolveAll([ assemblyPath ])) 19 | let dictionaries = ApiLoader.load assemblies 20 | return FSharpApiSearchClient([ assemblyName ], dictionaries) 21 | } 22 | 23 | let searchTest = parameterize { 24 | source [ 25 | "int -> int -> int", [ "TestModule.f"; "TestModule.TestClass.f" ] 26 | "int * int -> ?", [ "TestModule.f"; "TestModule.h"; "TestModule.TestClass.f"; "TestModule.TestClass.h" ] 27 | "?a -> ?a -> ?a", [ "TestModule.f"; "TestModule.g"; "TestModule.TestClass.f"; "TestModule.TestClass.g" ] 28 | ] 29 | run (fun (query, expecteds) -> test { 30 | let! client = testClient 31 | let actual = 32 | client.Search(query, TestHelper.defaultTestOptions) 33 | |> snd 34 | |> Seq.map (fun x -> FSharp.printFullName x.Api) |> Seq.toList |> List.sort 35 | do! actual |> assertEquals (List.sort expecteds) 36 | }) 37 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/FSharpCompilerServiceTest.fs: -------------------------------------------------------------------------------- 1 | [] 2 | module FSharpCompilerServiceTest 3 | 4 | open Persimmon 5 | open Persimmon.Syntax.UseTestNameByReflection 6 | open Persimmon.MuscleAssert 7 | open TestAssemblies 8 | open FSharp.Compiler.Symbols 9 | 10 | module InferredFloat = 11 | let ``is float`` (t: FSharpType) = test { 12 | let entity = t.TypeDefinition 13 | do! sprintf "%s.%s" entity.AccessPath entity.CompiledName |> assertEquals "Microsoft.FSharp.Core.float" 14 | do! entity.TryFullName |> assertEquals None 15 | do! t.GenericArguments.Count |> assertEquals 0 16 | } 17 | 18 | let targetClass = test { 19 | let! assemblies = assemblies 20 | let assembly = assemblies |> Array.find (fun x -> x.FileName = Some fsharpAssemblyPath ) 21 | return assembly.Contents.Entities |> Seq.find (fun x -> x.DisplayName = "StaticMemberClass") 22 | } 23 | 24 | let ``float is inferred to float`` = test { 25 | let! class' = targetClass 26 | let method' = class'.MembersFunctionsAndValues |> Seq.find (fun x -> x.DisplayName = "InferredFloat") 27 | do! ``is float`` method'.ReturnParameter.Type 28 | do! ``is float`` method'.CurriedParameterGroups.[0].[0].Type 29 | } 30 | 31 | let ``annotated float is float`` = test { 32 | let! class' = targetClass 33 | let method' = class'.MembersFunctionsAndValues |> Seq.find (fun x -> x.DisplayName = "AnnotatedFloat") 34 | do! ``is float`` method'.ReturnParameter.Type 35 | do! ``is float`` method'.CurriedParameterGroups.[0].[0].Type 36 | } 37 | 38 | let ``auto generic parameter`` = test { 39 | let! assemblies = assemblies 40 | let assembly = assemblies |> Array.find (fun x -> x.FileName = Some fsharpAssemblyPath) 41 | let module' = assembly.Contents.Entities |> Seq.find (fun x -> x.DisplayName = "PublicModule") 42 | let autoGenericFun = module'.MembersFunctionsAndValues |> Seq.find (fun x -> x.DisplayName = "autoGenericFunction") 43 | let parameter = autoGenericFun.CurriedParameterGroups.[0].[0] 44 | do! parameter.Type.ToString() |> assertEquals "type 'a" 45 | do! autoGenericFun.GenericParameters.[0].Name.StartsWith("?") |> assertEquals true 46 | } 47 | 48 | let ``Enum.value__ test`` = test { 49 | let! assemblies = assemblies 50 | let assembly = assemblies |> Array.find (fun x -> x.FileName = Some fsharpAssemblyPath ) 51 | let enum = assembly.Contents.Entities |> Seq.find (fun x -> x.DisplayName = "Enum") 52 | let value__ = enum.FSharpFields |> Seq.find (fun x -> x.DisplayName = "value__") 53 | do! value__.DisplayName |> assertEquals "value__" 54 | do! value__.IsCompilerGenerated |> assertEquals true 55 | } 56 | 57 | let ``ValueTuple test (F#)`` = test { 58 | let! assemblies = assemblies 59 | let assembly = assemblies |> Array.find (fun x -> x.FileName = Some fsharpAssemblyPath ) 60 | let module' = assembly.Contents.Entities |> Seq.find (fun x -> x.DisplayName = "FSharp41") 61 | let value = module'.MembersFunctionsAndValues |> Seq.find (fun x -> x.DisplayName = "structTuple") 62 | let actual = value.ReturnParameter.Type 63 | do! actual.IsTupleType |> assertEquals true 64 | do! actual.IsStructTupleType |> assertEquals true 65 | } 66 | 67 | let ``ValueTuple test (C#)`` = test { 68 | let! assemblies = assemblies 69 | let assembly = assemblies |> Array.find (fun x -> x.FileName = Some csharpAssemblyPath ) 70 | let class' = assembly.Contents.Entities |> Seq.find (fun x -> x.DisplayName = "Tuples") 71 | let method' = class'.MembersFunctionsAndValues |> Seq.find (fun x -> x.DisplayName = "G") 72 | let actual = method'.ReturnParameter.Type 73 | if actual.HasTypeDefinition then 74 | do! actual.TypeDefinition.FullName |> assertEquals "System.ValueTuple`2" 75 | do! actual.IsTupleType |> assertEquals false 76 | do! actual.IsStructTupleType |> assertEquals false 77 | else 78 | do! actual.IsTupleType |> assertEquals true 79 | do! actual.IsStructTupleType |> assertEquals true 80 | } 81 | 82 | let ``accesspath test`` = test { 83 | let! assemblies = assemblies 84 | let assembly = assemblies |> Array.find (fun x -> x.FileName = Some fsharpAssemblyPath ) 85 | let module' = assembly.Contents.Entities |> Seq.find (fun x -> x.DisplayName = "M2") 86 | 87 | let c = module'.DeclaringEntity |> Option.get 88 | do! c.DisplayName |> assertEquals "C" 89 | 90 | let b = c.DeclaringEntity |> Option.get 91 | do! b.DisplayName |> assertEquals "B" 92 | 93 | do! b.DeclaringEntity |> assertEquals None 94 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/HtmlPrintHelperTest.fs: -------------------------------------------------------------------------------- 1 | [] 2 | module HtmlPrintHelperTest 3 | 4 | open Persimmon 5 | open Persimmon.Syntax.UseTestNameByReflection 6 | //open Persimmon.MuscleAssert 7 | open FSharpApiSearch 8 | open FSharpApiSearch.HtmlPrintHelper 9 | 10 | let write str (x: StructuredWriter) = x.Write(str); x 11 | let begin' color (x: StructuredWriter) = x.BeginColor(color); x 12 | let end' color (x: StructuredWriter) = x.EndColor(color); x 13 | 14 | let writerTest = parameterize { 15 | source [ 16 | write "ab", [| ("ab", None) |] 17 | write "ab" >> write "cd", [| ("abcd", None) |] 18 | write "ab" >> begin' 1 >> write "cd" >> end' 1, [| ("ab", None); ("cd", Some 1) |] 19 | write "ab" >> begin' 1 >> write "cd" >> end' 1 >> write "ef", [| ("ab", None); ("cd", Some 1); ("ef", None) |] 20 | write "ab" >> begin' 1 >> write "cd" >> begin' 2 >> write "ef" >> end' 2 >> end' 1, [| ("ab", None); ("cd", Some 1); ("ef", Some 2) |] 21 | write "ab" >> begin' 1 >> write "cd" >> begin' 2 >> write "ef" >> end' 2 >> write "gh" >> end' 1, [| ("ab", None); ("cd", Some 1); ("ef", Some 2); ("gh", Some 1) |] 22 | begin' 1 >> write "ab" >> end' 1 >> write "cd", [| ("ab", Some 1); ("cd", None) |] 23 | begin' 1 >> write "a" >> end' 1 >> write " -> " >> begin' 2 >> write "b" >> end' 2 >> write " -> " >> begin' 3 >> write "c" >> end' 3, [| ("a", Some 1); (" -> ", None); ("b", Some 2); (" -> ", None); ("c", Some 3) |] 24 | ] 25 | run (fun (steps : StructuredWriter -> StructuredWriter, expected) -> test { 26 | let writer = StructuredWriter() 27 | let actual = (steps writer).Result.Text 28 | do! actual |> assertEquals expected 29 | }) 30 | } 31 | 32 | let printQueryTest = parameterize { 33 | source [ 34 | "a -> b -> c", [| ("a", Some 0); (" -> ", None); ("b", Some 1); (" -> ", None); ("c", Some 2) |] 35 | ] 36 | run (fun (input, expected) -> test { 37 | let query = QueryParser.FSharp.parse input |> QueryInitializer.queryPosition 38 | let actual = HtmlPrintHelper.query (QueryPrinter.print query) 39 | do! actual.Text |> assertEquals expected 40 | }) 41 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/Program.fs: -------------------------------------------------------------------------------- 1 | open Persimmon.Console 2 | open System.Reflection 3 | 4 | [] 5 | let main args = 6 | let args = Args.parse Args.empty (List.ofArray args) 7 | Runner.runTestsInAssembly args [ Assembly.GetExecutingAssembly() ] -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/QueryPrinterTest.fs: -------------------------------------------------------------------------------- 1 | [] 2 | module QueryPrinterTest 3 | 4 | open Persimmon 5 | open Persimmon.Syntax.UseTestNameByReflection 6 | open Persimmon.MuscleAssert 7 | open FSharpApiSearch 8 | 9 | let querySplitTest = parameterize { 10 | source [ 11 | "a -> b", [], [ "a -> b", None ] 12 | "a -> b", [ (QueryId 1, { Begin = 0; End = 1 }) ], [ ("a", Some (QueryId 1)); (" -> b", None) ] 13 | "a -> b -> c", [ (QueryId 1, { Begin = 5; End = 6 }) ], [ ("a -> ", None); ("b", Some (QueryId 1)); (" -> c", None) ] 14 | ] 15 | run (fun (query, ranges, expected) -> test { 16 | let actual = QueryPrinter.Impl.split query (Array.ofList ranges) 17 | do! actual |> assertEquals (Array.ofList expected) 18 | }) 19 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/TestAssemblies.fs: -------------------------------------------------------------------------------- 1 | module TestAssemblies 2 | 3 | open System 4 | open System.IO 5 | open System.Reflection 6 | open Persimmon 7 | open Persimmon.Syntax.UseTestNameByReflection 8 | open FSharpApiSearch 9 | 10 | let assemblyResolver: AssemblyLoader.AssemblyResolver = { 11 | FSharpCore = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 12 | Framework = 13 | [ 14 | Path.Combine( 15 | System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) 16 | , @"dotnet\shared\Microsoft.NETCore.App\" 17 | , string System.Environment.Version) 18 | ] 19 | Directories = [] 20 | } 21 | 22 | let fsharpAssemblyName = @"LoadTestAssembly" 23 | let fsharpAssemblyPath = 24 | Path.Combine( 25 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 26 | , fsharpAssemblyName + ".dll") 27 | 28 | let csharpAssemblyName = @"CSharpLoadTestAssembly"; 29 | let csharpAssemblyPath = 30 | Path.Combine( 31 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 32 | , csharpAssemblyName + ".dll") 33 | 34 | let valueTupleAssemblyName = @"System.ValueTuple" 35 | let valueTupleAssemblyPath = 36 | Path.Combine( 37 | Path.GetDirectoryName(Assembly.Load("System.ValueTuple").Location) 38 | , valueTupleAssemblyName + ".dll") 39 | 40 | let fparsecAssemblyName = @"FParsec"; 41 | let fparsecAssenmblyPath = 42 | Path.Combine( 43 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 44 | , fparsecAssemblyName + ".dll") 45 | 46 | let fparsecCSAssemblyName = @"FParsecCS"; 47 | let fparsecCSAssenmblyPath = 48 | Path.Combine( 49 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 50 | , fparsecCSAssemblyName + ".dll") 51 | 52 | let assemblies = test { 53 | let assemblies = [ 54 | yield Path.GetFullPath(fsharpAssemblyPath) 55 | yield Path.GetFullPath(csharpAssemblyPath) 56 | yield Path.GetFullPath(valueTupleAssemblyPath) 57 | yield Path.GetFullPath(fparsecAssenmblyPath) 58 | yield Path.GetFullPath(fparsecCSAssenmblyPath) 59 | ] 60 | return FSharpApiSearch.AssemblyLoader.load (assemblyResolver.ResolveAll(assemblies)) 61 | } 62 | 63 | let database = test { 64 | let! assemblies = assemblies 65 | return ApiLoader.load assemblies 66 | } 67 | 68 | let fsharpAssemblyApi = test { 69 | let! apiDictionary = database 70 | return apiDictionary |> Array.find (fun x -> x.AssemblyName = fsharpAssemblyName) 71 | } 72 | 73 | let csharpAssemblyApi = test { 74 | let! apiDictionary = database 75 | return apiDictionary |> Array.find (fun x -> x.AssemblyName = csharpAssemblyName) 76 | } 77 | 78 | let fscoreApi = test { 79 | let! apiDictionary = database 80 | return apiDictionary |> Array.find (fun x -> x.AssemblyName = "FSharp.Core") 81 | } 82 | 83 | let mscorlibApi = test { 84 | let! apiDictionary = database 85 | return apiDictionary |> Array.find (fun x -> x.AssemblyName = "System.Private.CoreLib") 86 | } 87 | 88 | let valueTupleApi = test { 89 | let! apiDictionary = database 90 | return apiDictionary |> Array.find (fun x -> x.AssemblyName = valueTupleAssemblyName) 91 | } 92 | 93 | let fparsecApi = test { 94 | let! apiDictionary = database 95 | return apiDictionary |> Array.find (fun x -> x.AssemblyName = fparsecAssemblyName) 96 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/TypesTest.fs: -------------------------------------------------------------------------------- 1 | module TypesTest 2 | 3 | open Persimmon 4 | open Persimmon.Syntax.UseTestNameByReflection 5 | open Persimmon.MuscleAssert 6 | open FSharpApiSearch 7 | 8 | open TestHelper.DSL 9 | open TestHelper.Types 10 | 11 | let parseDisplayNameTest = parameterize { 12 | source [ 13 | "A.B", [ { Name = SymbolName "B"; GenericParameters = [] }; { Name = SymbolName "A"; GenericParameters = [] } ] 14 | "A.B<'T>", [ { Name = SymbolName "B"; GenericParameters = [ tv "'T" ] }; { Name = SymbolName "A"; GenericParameters = [] } ] 15 | ] 16 | run (fun (x, expected) -> test { 17 | do! Name.ofString x |> assertEquals expected 18 | }) 19 | } 20 | 21 | let parseOperatorDisplayNameTest = parameterize { 22 | source [ 23 | "A.( + )", [ { Name = OperatorName ("( + )", "op_Addition"); GenericParameters = [] }; { Name = SymbolName "A"; GenericParameters = [] } ] 24 | ] 25 | run (fun (x, expected) -> test { 26 | do! Name.ofOperatorString x |> assertEquals expected 27 | }) 28 | } -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Tests/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FSharp.Compiler.Service 4 | System.ValueTuple 5 | MessagePack 6 | MessagePack.FSharpExtensions 7 | 8 | Persimmon 9 | Persimmon.Runner 10 | Persimmon.MuscleAssert -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Trace/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Trace/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace FSharpApiSearch.Trace.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // アセンブリに関する一般情報は、以下の属性セットによって 8 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 9 | // これらの属性値を変更します。 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 20 | // できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 21 | // その型の ComVisible 属性を true に設定します。 22 | [] 23 | 24 | // このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります 25 | [] 26 | 27 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されます。: 28 | // 29 | // メジャー バージョン 30 | // マイナー バージョン 31 | // ビルド番号 32 | // リビジョン 33 | // 34 | // すべての値を指定するか、下に示すように '*' を使用してビルドおよびリビジョン番号を 35 | // 既定値にすることができます。: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Trace/FSharpApiSearch.Trace.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | true 8 | FSharpApiSearch.Trace 9 | 3 10 | 11 | 12 | portable 13 | false 14 | 15 | 16 | portable 17 | true 18 | 19 | 20 | true 21 | portable 22 | false 23 | false 24 | DEBUG;TRACE 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Trace/Program.fs: -------------------------------------------------------------------------------- 1 | module FSharpApiSearch.Trace.Program 2 | 3 | open FSharpApiSearch 4 | open FSharpApiSearch.StringPrinter 5 | open FSharpApiSearch.Console 6 | open System 7 | open System.Diagnostics 8 | open System.IO 9 | 10 | let assemblyResolver: AssemblyLoader.AssemblyResolver = { 11 | FSharpCore = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0\") 12 | Framework = [ Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\") ] 13 | Directories = [] 14 | } 15 | 16 | let positionPrintVisitor printPos lowType = 17 | let rec print lowType = 18 | printPos lowType; 19 | match lowType with 20 | | Wildcard _ -> () 21 | | Variable _ -> () 22 | | Identifier _ -> () 23 | | Arrow ((xs, x), _) -> List.iter print xs; print x 24 | | Tuple (tpl, _) -> List.iter print tpl.Elements 25 | | Generic (id, args, _) -> print id; List.iter print args 26 | | TypeAbbreviation (abb, _) -> print abb.Abbreviation; print abb.Original 27 | | Delegate (t, (xs, x), _) -> print t; List.iter print xs; print x 28 | | ByRef (_, t, _) -> print t 29 | | LowType.Subtype (t, _) -> print t 30 | | Choice (o, xs, _) -> print o; List.iter print xs 31 | | LoadingType _ -> () 32 | 33 | print lowType 34 | lowType 35 | 36 | let printQueryPositions (query: Query) = 37 | printfn "Query Positions:" 38 | query 39 | |> LowTypeVisitor.accept_Query (positionPrintVisitor (fun x -> 40 | match x.Position with 41 | | AtQuery (Some id, _) -> printfn " %A : %A" id (x.Print()) 42 | | _ -> () 43 | )) 44 | |> ignore 45 | 46 | let printSignaturePositions (api: Api) = 47 | printfn "Signature Positions:" 48 | api.Signature 49 | |> LowTypeVisitor.accept_ApiSignature (positionPrintVisitor (fun x -> 50 | match x.Position with 51 | | AtSignature (id) -> printfn " %A : %A" id (x.Print()) 52 | | _ -> () 53 | )) 54 | |> ignore 55 | 56 | [] 57 | let main argv = 58 | let args = Args.parse Args.empty (List.ofArray argv) 59 | let options = args.SearchOptions |> SearchOptions.Parallel.Set Disabled 60 | 61 | let dictionaries = Database.loadFromFile Database.databaseName 62 | let targets = Args.targetsOrDefault args 63 | let targetAssemblies = dictionaries |> Seq.filter (fun x -> targets |> Seq.exists ((=)x.AssemblyName)) |> Seq.toArray 64 | 65 | let apis = targetAssemblies |> Seq.collect (fun x -> x.Api) |> Seq.toArray 66 | 67 | use listener = new TextWriterTraceListener(System.Console.Out) 68 | Trace.Listeners.Add(listener) |> ignore 69 | Debug.IndentSize <- 2 70 | 71 | let rec loop() = 72 | try 73 | Console.WriteLine("input query.") 74 | Console.Write("> "); 75 | let query = Console.ReadLine() 76 | 77 | if query = "" then 78 | () 79 | else 80 | Console.WriteLine("input target name.") 81 | Console.Write("> "); 82 | let targetName = Console.ReadLine() 83 | 84 | let target = apis |> Array.find (fun x -> FSharp.printFullName x = targetName) 85 | let dummyDict: ApiDictionary = { AssemblyName = "dummy"; Api = [| target |]; TypeDefinitions = dict Seq.empty; TypeAbbreviations = [||] } 86 | let resultQuery, result = Engine.search dictionaries options [ dummyDict ] query 87 | 88 | printfn "Result = %b" (Seq.isEmpty result = false) 89 | result 90 | |> Seq.iter (fun x -> 91 | printfn "Match Positions:" 92 | x.MatchPositions 93 | |> Map.iter (fun sigId queryId -> 94 | printfn " %A : %A" queryId sigId 95 | ) 96 | ) 97 | 98 | printQueryPositions resultQuery 99 | printSignaturePositions target 100 | 101 | loop() 102 | with 103 | ex -> 104 | printfn "%A" ex 105 | loop() 106 | 0 -------------------------------------------------------------------------------- /tests/FSharpApiSearch.Trace/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FSharp.Compiler.Service 4 | MessagePack 5 | MessagePack.FSharpExtensions -------------------------------------------------------------------------------- /tests/LoadTestAssembly/AccessPath.fs: -------------------------------------------------------------------------------- 1 | namespace A 2 | module M1 = () 3 | namespace B.C 4 | module M2 = () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace LoadTestAssembly.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // アセンブリに関する一般情報は、以下の属性セットによって 8 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 9 | // これらの属性値を変更します。 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 20 | // できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 21 | // その型の ComVisible 属性を true に設定します。 22 | [] 23 | 24 | // このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります 25 | [] 26 | 27 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されます。: 28 | // 29 | // メジャー バージョン 30 | // マイナー バージョン 31 | // ビルド番号 32 | // リビジョン 33 | // 34 | // すべての値を指定するか、下に示すように '*' を使用してビルドおよびリビジョン番号を 35 | // 既定値にすることができます。: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/Class.fs: -------------------------------------------------------------------------------- 1 | namespace TopLevelNamespace 2 | 3 | type StaticMemberClass() = 4 | new (x: int) = StaticMemberClass() 5 | 6 | static member NoParameterMethod () = 3 7 | static member OneParameterMethod (x: int) = 3 8 | static member NonCurriedMethod (x: int, y: string) = x 9 | static member CurriedMethod (x: int) (y: string) = x 10 | static member TupleMethod (x: int * string) = fst x 11 | 12 | static member InferredFloat (x) = 0.0 + x 13 | static member AnnotatedFloat (x: float): float = 0.0 14 | 15 | static member OverloadMethod (x: int) = 0 16 | static member OverloadMethod (x: string, y: int) = "" 17 | 18 | static member Getter with get() = "" 19 | static member Setter with set(_: int) = () 20 | static member GetterSetter with get() = 0.0 and set(_: float) = () 21 | 22 | static member IndexedGetter with get(_: int) = "" 23 | static member IndexedSetter with set(_: int) (_: string) = () 24 | static member IndexedGetterSetter with get(_: string) = 0 and set(_: string) (_: int) = () 25 | 26 | static member private PrivateMethod() = 0 27 | static member internal InternalMethod() = 0 28 | 29 | static member GenericMethod(x: 'a) = x 30 | 31 | type InstanceMemberClass() = 32 | member this.NoParameterMethod () = 3 33 | member this.OneParameterMethod (x: int) = 3 34 | member this.NonCurriedMethod (x: int, y: string) = x 35 | member this.CurriedMethod (x: int) (y: string) = x 36 | member this.TupleMethod (x: int * string) = fst x 37 | 38 | member this.OverloadMethod (x: int) = 0 39 | member this.OverloadMethod (x: string, y: int) = "" 40 | 41 | member this.Getter with get() = "" 42 | member this.Setter with set(_: int) = () 43 | member this.GetterSetter with get() = 0.0 and set(_: float) = () 44 | 45 | member this.IndexedGetter with get(_: int) = "" 46 | member this.IndexedSetter with set(_: int) (_: string) = () 47 | member this.IndexedGetterSetter with get(_: string) = 0 and set(_: string) (_: int) = () 48 | 49 | type private PrivateClass() = 50 | static member PublicMethod() = 0 51 | 52 | type internal InternalClass() = 53 | static member PublicMethod() = 0 54 | 55 | type GenericClass<'a>() = 56 | member this.Method(x: 'a) = 3 57 | member this.GenericMethod(x: 'b) = x 58 | 59 | type Interface = interface 60 | abstract member Method: int * string -> int 61 | abstract member Property: string with get, set 62 | abstract member GenericMethod: 'a -> 'a 63 | end -------------------------------------------------------------------------------- /tests/LoadTestAssembly/CompiledNames.fs: -------------------------------------------------------------------------------- 1 | module CompiledNames 2 | 3 | let withoutCompiledName () = () 4 | 5 | [] 6 | let funcName () = () 7 | 8 | [] 9 | type TypeName() = class end 10 | 11 | type T() = 12 | [] 13 | static member MethodName() = () 14 | 15 | static member WithoutCompiledNameProperty = 3 16 | 17 | [] 18 | static member PropertyName = 3 19 | 20 | type Record = { 21 | [] 22 | FieldName: int 23 | } 24 | 25 | type Union = | [] CaseName of int 26 | 27 | [] 28 | module ModuleName = () 29 | 30 | [] 31 | module WithModuleSuffix = 32 | let f () = () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/ComputationExpression.fs: -------------------------------------------------------------------------------- 1 | module ComputationExpression 2 | 3 | type OptionBuilder() = 4 | member this.Bind(x: option<'a>, f: 'a -> 'b option) = Option.bind f x 5 | member this.Return(x: 'a) = Some x 6 | member this.ReturnFrom(x: option<'a>) = x 7 | 8 | let option = OptionBuilder() 9 | let option2 _ = OptionBuilder() 10 | 11 | do 12 | let x = option { 13 | let! x = Some 3 14 | return x 15 | } 16 | () 17 | 18 | type NotBuilder() = 19 | member this.Run() = Option.None 20 | 21 | let notBuilder = NotBuilder() 22 | 23 | type TryFinallyTest = TryFinallyTest 24 | type GenericDelayBuilder() = 25 | member this.Zero() = TryFinallyTest 26 | member this.TryFinally(f, g) = try f finally g() 27 | member this.Delay(_) = TryFinallyTest 28 | 29 | let genericDelay = GenericDelayBuilder() 30 | 31 | do 32 | let x = genericDelay { try () finally () } 33 | () 34 | 35 | type DelayBuilder() = 36 | member this.Zero() = TryFinallyTest 37 | member this.TryFinally(f, g) = try f finally g() 38 | member this.Delay(f) = f() 39 | 40 | let delay = DelayBuilder() 41 | 42 | do 43 | let x = delay { try () finally () } 44 | () 45 | 46 | type CustomOperation = CustomOperation 47 | type CustomOperationBuilder() = 48 | [] 49 | member this.Test(value: 'a) = CustomOperation 50 | 51 | member this.Yield(x: 'a) = x 52 | 53 | let customOperation = CustomOperationBuilder() 54 | 55 | do 56 | let x = customOperation { test } 57 | () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/Delegate.fs: -------------------------------------------------------------------------------- 1 | module Delegate 2 | 3 | open System 4 | 5 | type TestDelegate = delegate of int * int -> bool 6 | type GenericDelegate<'a, 'b> = delegate of 'a * 'b -> bool 7 | 8 | let f1 = TestDelegate(fun _ _ -> true) 9 | let f2 (x: 'a) (f: TestDelegate) = 0 10 | 11 | let f3 (f: GenericDelegate<'a, 'b>) = 0 12 | let f4 (f: GenericDelegate) = 0 13 | 14 | let f5 (f: Func) = true -------------------------------------------------------------------------------- /tests/LoadTestAssembly/FSharp41.fs: -------------------------------------------------------------------------------- 1 | module FSharp41 2 | 3 | let tuple = (1, "a") 4 | let structTuple = struct (1, "a") 5 | 6 | [] 7 | type StructRecord = { 8 | FieldA: int 9 | FieldB: string 10 | } 11 | 12 | [] 13 | type StructUnion = A of a:string | B of b:int * c:string -------------------------------------------------------------------------------- /tests/LoadTestAssembly/FullTypeDefinition.fs: -------------------------------------------------------------------------------- 1 | module FullTypeDefinition 2 | 3 | (* Subtype Constraints *) 4 | type PlainClass() = class end 5 | 6 | type PlainInterface = interface end 7 | 8 | type InterfaceImplClass() = 9 | interface PlainInterface 10 | 11 | type InterfaceInherit = 12 | inherit PlainInterface 13 | 14 | (* Nullness Constraints *) 15 | 16 | [] 17 | type SupportNullClass() = class end 18 | 19 | type SupportNullSubClass() = inherit SupportNullClass() 20 | 21 | [] 22 | type SupportNullInterface = interface end 23 | 24 | type NonSupportNullSubInterface = inherit SupportNullInterface 25 | 26 | [] 27 | type SupportNullSubInterface = inherit SupportNullInterface 28 | 29 | (* 30 | let f<'a when 'a : null> (x: 'a) = () 31 | do f (SupportNullClass()) // OK 32 | do f (SupportNullSubClass()) // NG 33 | do f ({ new SupportNullInterface }) // OK 34 | do f ({ new NonSupportNullSubInterface }) // OK 35 | do f ({ new SupportNullSubInterface }) // OK 36 | *) 37 | 38 | type MemberClass() = 39 | static member StaticMethod () = 0 40 | static member (+) (x: MemberClass, y: int) = x 41 | member this.InstanceMethod (_: int) = 0 42 | member this.Property = 0 43 | 44 | type WithoutDefaultConstructor(x: int) = class end 45 | 46 | module EqualityConstraints = 47 | type EqualityType() = class end 48 | 49 | [] 50 | type NoEqualityType() = class end 51 | 52 | type InferredEqualityRecord = { 53 | X: int 54 | Y: string 55 | } 56 | 57 | type InferredNoEqualityRecord = { 58 | X: int 59 | Y: int -> int 60 | } 61 | 62 | type InferredEqualityUnion = 63 | | A of int 64 | | B of string 65 | 66 | type InferredNoEqualityUnion = 67 | | A of int 68 | | B of NoEqualityType 69 | 70 | [] 71 | type CustomEqualityRecord = { 72 | X: int -> int 73 | } 74 | with 75 | override this.Equals(_) = true 76 | override this.GetHashCode() = 0 77 | 78 | type GenericClass<'a, 'b>() = class end 79 | type EqualityConditionalClass<[]'a, 'b>() = class end 80 | 81 | [] 82 | type CustomEqualityAndConditionalRecord<[]'a, 'b> = { 83 | X: 'a 84 | Y: 'b 85 | } 86 | with 87 | override this.Equals(_) = true 88 | override this.GetHashCode() = 0 89 | 90 | type EqualityGenericRecord<'a,'b> = { 91 | X: 'a 92 | Y: 'b 93 | Z: int 94 | } 95 | 96 | type NoEqualityGenericRecord<'a, 'b> = { 97 | X: 'a 98 | Y: 'b 99 | Z: int -> int 100 | } 101 | 102 | type EqualityWithGenericType = { 103 | X: list 104 | } 105 | 106 | type NoEqualityWithGenericType = { 107 | X: list int> 108 | } 109 | 110 | type RecursiveType<'a> = 111 | | A of 'a * RecursiveType<'a> 112 | | B 113 | 114 | type TupleAbbreviation = int * string 115 | type TupleAbbreviationFieldRecord = { 116 | Tuple : TupleAbbreviation 117 | } 118 | 119 | type FunctionAbbreviation = int -> string 120 | type FunctionAbbreviationFieldRecord = { 121 | Function : FunctionAbbreviation 122 | } 123 | 124 | type AbbreviatedGenericParameter<'a> = 'a 125 | type AbbreviatedGenericParameterField<'a> = { 126 | A: AbbreviatedGenericParameter<'a> 127 | } 128 | 129 | type AbbreviatedGenericParameterInt = { 130 | A: AbbreviatedGenericParameter 131 | } 132 | 133 | module ComparisonConstraints = 134 | open System 135 | open System.Collections 136 | 137 | type ComparisonType() = 138 | override this.Equals(_) = true 139 | override this.GetHashCode() = 0 140 | interface IComparable with 141 | member this.CompareTo(_) = 0 142 | 143 | type NotComparisonType() = 144 | interface IComparable with 145 | member this.CompareTo(_) = 0 146 | 147 | type StructualComparisonType() = 148 | interface IStructuralComparable with 149 | member this.CompareTo(_, _) = 0 150 | 151 | type InferredComparisonRecord = { 152 | X: int 153 | Y: string 154 | } 155 | 156 | type InferredNoComparisonRecord = { 157 | X: int 158 | Y: int -> int 159 | } 160 | 161 | [] 162 | type NoComparisonRecord = { 163 | X: int 164 | Y: string 165 | } 166 | 167 | type InferredComparisonUnion = 168 | | A of int 169 | | B of string 170 | 171 | type InferredNoComparisonUnion = 172 | | A of int 173 | | B of NotComparisonType 174 | 175 | [] 176 | type CustomComparisonRecord = { 177 | X: int -> int 178 | } 179 | with 180 | override this.Equals(_) = true 181 | override this.GetHashCode() = 0 182 | interface IComparable with 183 | member this.CompareTo(_) = 0 184 | 185 | type GenericNoComparisonClass<'a, 'b>() = class end 186 | 187 | type GenericComparisonClass<'a, 'b>() = 188 | override this.Equals(_) = true 189 | override this.GetHashCode() = 0 190 | interface IComparable with 191 | member this.CompareTo(_) = 0 192 | 193 | type ComparisonConditionalClass<[]'a, 'b>() = 194 | override this.Equals(_) = true 195 | override this.GetHashCode() = 0 196 | interface IComparable with 197 | member this.CompareTo(_) = 0 198 | 199 | [] 200 | type CustomComparisonAndConditionalRecord<[]'a, 'b> = { 201 | X: 'a 202 | Y: 'b 203 | } 204 | with 205 | override this.Equals(_) = true 206 | override this.GetHashCode() = 0 207 | interface IComparable with 208 | member this.CompareTo(_) = 0 209 | 210 | type ComparisonGenericRecord<'a, 'b> = { 211 | X: 'a 212 | Y: 'b 213 | Z: int 214 | } 215 | 216 | type NoComparisonGenericRecord<'a, 'b> = { 217 | X: 'a 218 | Y: 'b 219 | Z: int -> int 220 | } 221 | 222 | type ComparisonWithGenericType = { 223 | X: list 224 | } 225 | 226 | type NoComparisonWithGenericType = { 227 | X: list int> 228 | } 229 | 230 | type RecursiveType<'a> = 231 | | A of 'a * RecursiveType<'a> 232 | | B 233 | 234 | let test<'a when 'a : comparison>(_: 'a) = () 235 | 236 | type TupleAbbreviation = int * string 237 | type TupleAbbreviationFieldRecord = { 238 | Tuple : TupleAbbreviation 239 | } 240 | 241 | type FunctionAbbreviation = int -> string 242 | type FunctionAbbreviationFieldRecord = { 243 | Function : FunctionAbbreviation 244 | } 245 | 246 | type AbbreviatedGenericParameter<'a> = 'a 247 | type AbbreviatedGenericParameterField<'a> = { 248 | A: AbbreviatedGenericParameter<'a> 249 | } 250 | 251 | type AbbreviatedGenericParameterInt = { 252 | A: AbbreviatedGenericParameter 253 | } 254 | 255 | type PublicType() = class end 256 | type private PrivateType() = class end 257 | type internal InternalType() = class end -------------------------------------------------------------------------------- /tests/LoadTestAssembly/InternalModule.fs: -------------------------------------------------------------------------------- 1 | module internal InternalModule 2 | 3 | let publicFunction x y = 0 -------------------------------------------------------------------------------- /tests/LoadTestAssembly/InternalSignature.fs: -------------------------------------------------------------------------------- 1 | module InternalSignature 2 | 3 | type InternalType = A 4 | 5 | let f () = A -------------------------------------------------------------------------------- /tests/LoadTestAssembly/InternalSignature.fsi: -------------------------------------------------------------------------------- 1 | module InternalSignature 2 | 3 | type internal InternalType 4 | 5 | val f : unit -> InternalType -------------------------------------------------------------------------------- /tests/LoadTestAssembly/LoadTestAssembly.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | true 6 | true 7 | LoadTestAssembly 8 | 3 9 | 10 | 11 | portable 12 | false 13 | 14 | 15 | portable 16 | true 17 | 18 | 19 | true 20 | portable 21 | false 22 | false 23 | DEBUG;TRACE 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /tests/LoadTestAssembly/Operators.fs: -------------------------------------------------------------------------------- 1 | module Operators 2 | 3 | let (+) x y = x + y 4 | 5 | type A() = 6 | static member (-) (x: A, y: A) = x -------------------------------------------------------------------------------- /tests/LoadTestAssembly/OptionalParameters.fs: -------------------------------------------------------------------------------- 1 | module OptionalParameters 2 | 3 | open System.Runtime.InteropServices 4 | 5 | type X() = 6 | member this.F(x: int, ?y: string) = x 7 | member this.G(x: string option, ?y: int option) = x 8 | member this.H([]x: string) = x -------------------------------------------------------------------------------- /tests/LoadTestAssembly/OtherTypes.fs: -------------------------------------------------------------------------------- 1 | namespace OtherTypes 2 | 3 | type Record = { 4 | FieldA: int 5 | FieldB: string 6 | } 7 | with 8 | member this.InstanceMethod() = 0 9 | member this.InstanceProperty with get() = 0 and set(_: int) = () 10 | static member StaticMethod() = "" 11 | 12 | type GenericRecord<'a> = { 13 | Field: 'a 14 | } 15 | 16 | type Union = A | B of int * field2:string | C of int | D of field:int 17 | with 18 | member this.InstanceMethod() = 0 19 | 20 | type Enum = A = 0 | B = 1 21 | 22 | type Struct = struct 23 | val A: int 24 | val B: string 25 | 26 | member this.InstanceMethod() = 0 27 | end -------------------------------------------------------------------------------- /tests/LoadTestAssembly/ParamArray.fs: -------------------------------------------------------------------------------- 1 | module ParamArray 2 | 3 | type X() = 4 | member this.F([]xs: int[]) = () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/PrivateModule.fs: -------------------------------------------------------------------------------- 1 | module private PrivateModule 2 | 3 | let publicFunction x y = 0 -------------------------------------------------------------------------------- /tests/LoadTestAssembly/PublicModule.fs: -------------------------------------------------------------------------------- 1 | module PublicModule 2 | 3 | let nonGenericFunction (x: int) (y: int) = 3 4 | 5 | let genericFunction (x: 'a) (y : 'b) = y 6 | 7 | let multiParamFunction (x: 'a, y: 'b, z: 'c) = x 8 | 9 | let autoGenericFunction x = x 10 | let autoGenericFunction2 (x: 'a) y z = x 11 | let autoGenericFunction3 x (y: 'b) z = x 12 | let autoGenericFunction4 x y (z: 'c) = x 13 | let autoGenericFunction5 (x: 'a0) y z = x 14 | let autoGenericFunction6 (x: 'a) (y: 'a0) z = x 15 | 16 | let flexible (x: #seq<_>) = () 17 | 18 | let unitParamFunction () = 0 19 | 20 | let listmap (f: 'a -> 'b) (xs: 'a list) = List.map f xs 21 | 22 | let partialGenericMap (x: Map) = x.Item(3) 23 | 24 | let internal internalFunction x = x 25 | 26 | let private privateFunction x y = y 27 | 28 | let value = 3 29 | 30 | let floatReturnType (x: int): float = 0.0 31 | 32 | let array: int[] = Array.zeroCreate 0 33 | let array2d: int[,] = Array2D.zeroCreate 0 0 34 | let nestedArray: int[,][] = Array.zeroCreate 0 35 | 36 | let (|ActivePattern|) x = if x = 1 then "one" else string x 37 | let (|PartialActivePattern|_|) (y: 'a) (x: 'a) = if x = y then Some x else None 38 | 39 | module NestedModule = 40 | let publicFunction (x: int) = 3 -------------------------------------------------------------------------------- /tests/LoadTestAssembly/TypeAbbreviations.fs: -------------------------------------------------------------------------------- 1 | module TypeAbbreviations 2 | 3 | type Original<'a> = Original of 'a 4 | 5 | type A = A 6 | 7 | type GenericTypeAbbreviation<'b> = Original<'b> 8 | type SpecializedTypeAbbreviation = Original 9 | 10 | type NestedTypeAbbreviation = SpecializedTypeAbbreviation 11 | 12 | type FunctionAbbreviation = int -> int 13 | 14 | let functionWithFunctionAbbreviation (x: FunctionAbbreviation): FunctionAbbreviation = x 15 | 16 | module NestedModule = 17 | type TypeAbbreviationInModule<'a> = Original<'a> 18 | 19 | type internal InternalTypeAbbreviation = A 20 | type private PrivateTypeAbbreviation = A -------------------------------------------------------------------------------- /tests/LoadTestAssembly/TypeConstraints.fs: -------------------------------------------------------------------------------- 1 | module TypeConstraints 2 | 3 | let subtypeConFunction<'Tseq when 'Tseq :> seq> (x: 'Tseq) = () 4 | 5 | type SubTypeClass<'a when 'a :> seq>() = 6 | static member Method<'b when 'b :> seq>(x: 'a, y: 'b) = () 7 | 8 | type SubTypeRecord<'a when 'a :> seq> = { 9 | Field: 'a 10 | } 11 | 12 | let nullnessFunction<'a when 'a : null> (x: 'a) = () 13 | 14 | let inline memberConstraint_instanceMethod1<'a when 'a : (member Method : int -> int -> int)> (x: 'a) = () 15 | let inline memberConstraint_instanceMethod2<'a when 'a : (member Method : int * int -> int)> (x: 'a) = () 16 | let inline memberConstraint_tupleMethod<'a when 'a : (member Method : (int * int) -> int)> (x: 'a) = () 17 | let inline memberConstraint_staticMember<'a when 'a : (static member Method : int -> int)> (x: 'a) = () 18 | let inline memberConstraint_or<'a, 'b when ('a or 'b) : (static member Method : int -> int)> (x: 'a) (y: 'b) = () 19 | let inline memberConstraint_noArgumentMember<'a when 'a : (member Method: int)> (x: 'a) = () 20 | let inline memberConstraint_unitMethod<'a when 'a : (member Method: unit -> int)> (x: 'a) = () 21 | let inline memberConstraint_unitIntMethod<'a when 'a : (member Method: unit -> int -> int)> (x: 'a) = () 22 | let inline memberConstraint_getterMethod<'a when 'a : (member get_Property : unit -> int)> (x: 'a) = () 23 | let inline memberConstraint_setterMethod<'a when 'a : (member set_Property : int -> unit)> (x: 'a) = () 24 | let inline memberConstraint_getProperty<'a when 'a : (member Property : int with get)> (x: 'a) = () 25 | let inline memberConstraint_setProperty<'a when 'a : (member Property : int with set)> (x: 'a) = () 26 | let inline memberConstraint_indexedGetProperty<'a when 'a : (member Property : int -> int with get)> (x: 'a) = () 27 | let inline memberConstraint_indexedSetProperty<'a when 'a : (member Property : int -> int with set)> (x: 'a) = () 28 | 29 | let inline memberConstraint_staticNoArgumentMember<'a when 'a : (static member Method: int)> (x: 'a) = () 30 | let inline memberConstraint_staticUnitMethod<'a when 'a : (static member Method: unit -> int)> (x: 'a) = () 31 | let inline memberConstraint_staticGetterMethod<'a when 'a : (static member get_Property: unit -> int)> (x: 'a) = () 32 | let inline memberConstraint_staticSetterMethod<'a when 'a : (static member set_Property: int -> unit)> (x: 'a) = () 33 | let inline memberConstraint_staticGetProperty<'a when 'a : (static member Property: int with get)> (x: 'a) = () 34 | let inline memberConstraint_staticSetProperty<'a when 'a : (static member Property: int with set)> (x: 'a) = () 35 | 36 | let inline memberConstraint_generic<'a, 'b when 'a : (member Method: 'b -> unit)> (x: 'a) = () 37 | 38 | let inline memberConstraint_operator<'a, 'b, 'c when ('a or 'b) : (static member (+): 'a -> 'b -> 'c)> (x: 'a) (y: 'b) = () 39 | 40 | let valueTypeConstraint<'a when 'a : struct> (x: 'a) = () 41 | let referenceTypeConstraint<'a when 'a : not struct> (x: 'a) = () 42 | 43 | let defaultConstructorConstraint<'a when 'a : (new : unit -> 'a)> (x: 'a) = () 44 | 45 | let equalityConstraint<'a when 'a : equality> (x: 'a) = () 46 | let comparisonConstraint<'a when 'a : comparison> (x: 'a) = () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/TypeExtensions.fs: -------------------------------------------------------------------------------- 1 | module TypeExtensions 2 | 3 | type System.Int32 with 4 | member this.Method(x: int) = () 5 | member this.CurriedMethod (x: int) (y: string) = x 6 | member this.NoncurriedMethod (x: int, y: string) = y 7 | 8 | member this.GetterProperty with get() = 3 9 | member this.SetterProperty with set(value: string) = () 10 | member this.GetterSetterProperty with get() = "" and set (value: string) = () 11 | 12 | member this.GetterIndexedProperty with get(_: int) = "" 13 | member this.SetterIndexedProperty with set (_: int) (_: string) = () 14 | member this.GetterSetterIndexedProperty with get (_: string) = 0 and set (_: string) (_: int) = () 15 | 16 | let private f (x: #seq) = x 17 | 18 | type List<'a> with 19 | static member Method(_: 'a) = () 20 | static member CurriedMethod (x: int) (y: 'b) = y 21 | static member NoncurriedMethod (x: int, y: 'b) = x 22 | 23 | static member GetterProperty with get() = 3 24 | static member SetterProperty with set(value: string) = () 25 | static member GetterSetterProperty with get() = "" and set (value: string) = () 26 | 27 | static member GetterIndexedProperty with get(_: int) = "" 28 | static member SetterIndexedProperty with set (_: int) (_: string) = () 29 | static member GetterSetterIndexedProperty with get (_: string) = 0 and set (_: string) (_: int) = () 30 | 31 | member this.AutoGenericMember() = f 32 | 33 | open System.Runtime.CompilerServices 34 | 35 | [] 36 | type TestExtensions private () = 37 | [] 38 | static member ExtensionMethod(x: int) = x 39 | [] 40 | static member ExtensionMethod2(x: int, y: int, z: string) = () -------------------------------------------------------------------------------- /tests/LoadTestAssembly/XmlDoc.fs: -------------------------------------------------------------------------------- 1 | module XmlDoc 2 | 3 | /// this is comment 4 | type Type() = class end 5 | 6 | /// this is function comment 7 | let f() = () 8 | 9 | type NoComment() = class end -------------------------------------------------------------------------------- /tests/LoadTestAssembly/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | System.ValueTuple -------------------------------------------------------------------------------- /tests/PerformanceTest/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/PerformanceTest/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace PerformanceTest.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // アセンブリに関する一般情報は、以下の属性セットによって 8 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 9 | // これらの属性値を変更します。 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 20 | // できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 21 | // その型の ComVisible 属性を true に設定します。 22 | [] 23 | 24 | // このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります 25 | [] 26 | 27 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されます。: 28 | // 29 | // メジャー バージョン 30 | // マイナー バージョン 31 | // ビルド番号 32 | // リビジョン 33 | // 34 | // すべての値を指定するか、下に示すように '*' を使用してビルドおよびリビジョン番号を 35 | // 既定値にすることができます。: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /tests/PerformanceTest/PerformanceTest.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | PerformanceTest 8 | true 9 | 3 10 | 11 | 12 | portable 13 | false 14 | 15 | 16 | portable 17 | true 18 | 19 | 20 | true 21 | portable 22 | false 23 | false 24 | DEBUG;TRACE 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/PerformanceTest/Program.fs: -------------------------------------------------------------------------------- 1 | open FSharpApiSearch 2 | open BenchmarkDotNet 3 | open BenchmarkDotNet.Attributes 4 | open BenchmarkDotNet.Running 5 | 6 | [] 7 | [] 8 | type MyBenchmarks() = 9 | let mutable client : FSharpApiSearchClient = Unchecked.defaultof<_> 10 | 11 | let parallelOpt = SearchOptions.defaultOptions |> SearchOptions.Parallel.Set Enabled 12 | let nonParallelOpt = SearchOptions.defaultOptions |> SearchOptions.Parallel.Set Disabled 13 | 14 | [] 15 | member this.GlobalSetup() = 16 | let targets = FSharpApiSearchClient.DefaultTargets 17 | let database = Database.loadFromFile Database.databaseName 18 | client <- FSharpApiSearchClient(targets, database) 19 | 20 | [", 23 | "seq<'a> -> 'a", 24 | "?a -> ?a", 25 | "?a -> ?b -> ?a", 26 | "('a -> 'b) -> ?<'a> -> ?<'b>", 27 | "int -> #seq<'a>", 28 | "#seq<#obj> -> int", 29 | "#seq<'a> -> int", 30 | "#seq -> ?a", 31 | "List*.* : _", 32 | "*List.* : _", 33 | "*List*.* : _", 34 | "*L*t*.* : _" 35 | )>] 36 | member val Query = "" with get, set 37 | 38 | [] 39 | member this.Parallel() = client.Search(this.Query, parallelOpt) |> snd |> ResizeArray 40 | 41 | [] 42 | member this.NonParallel() = client.Search(this.Query, nonParallelOpt) |> snd |> ResizeArray 43 | 44 | [] 45 | let main argv = 46 | let summary = BenchmarkRunner.Run() 47 | 0 48 | -------------------------------------------------------------------------------- /tests/PerformanceTest/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FSharp.Compiler.Service 4 | MessagePack 5 | MessagePack.FSharpExtensions 6 | 7 | BenchmarkDotNet -------------------------------------------------------------------------------- /tests/Profiling/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/Profiling/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace Profiling.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /tests/Profiling/Profiling.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | true 8 | Profiling 9 | true 10 | 3 11 | 12 | 13 | portable 14 | false 15 | 16 | 17 | portable 18 | true 19 | 20 | 21 | true 22 | portable 23 | false 24 | false 25 | DEBUG;TRACE 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/Profiling/Program.fs: -------------------------------------------------------------------------------- 1 | open FSharpApiSearch 2 | open System.Diagnostics 3 | open System.Threading.Tasks 4 | open System.Threading 5 | 6 | type TestResult = { 7 | Query: string 8 | Count: int 9 | AverageTimeNonParallel: int64 10 | AverageTimeParallel: int64 11 | } 12 | 13 | let queries = [ 14 | "ToString" 15 | "seq<'t>" 16 | "seq<'a> -> 'a" 17 | "?a -> ?a" 18 | "?a -> ?b -> ?a" 19 | "('a -> 'b) -> ?<'a> -> ?<'b>" 20 | "int -> #seq<'a>" 21 | "#seq<#obj> -> int" 22 | "#seq<'a> -> int" 23 | "#seq -> ?a" 24 | "List*.* : _" 25 | "*List.* : _" 26 | "*List*.* : _" 27 | "*L*t*.* : _" 28 | ] 29 | 30 | [] 31 | let main argv = 32 | let client = 33 | let targets = FSharpApiSearchClient.DefaultTargets 34 | let database = Database.loadFromFile Database.databaseName 35 | FSharpApiSearchClient(targets, database) 36 | 37 | let run query option = 38 | let sw = Stopwatch.StartNew() 39 | let results = 40 | client.Search(query, option) 41 | |> snd 42 | |> ResizeArray 43 | sw.Stop() 44 | (float results.Count, float sw.ElapsedMilliseconds) 45 | 46 | let skip = 3 47 | let n = skip + 50 48 | 49 | let nonParallelOpt = SearchOptions.defaultOptions |> SearchOptions.Parallel.Set Disabled 50 | let parallelOpt = SearchOptions.defaultOptions |> SearchOptions.Parallel.Set Enabled 51 | 52 | printfn "query\tcount\tnon parallel\tparallel" 53 | 54 | for x = 1 to 10 do 55 | run "int -> string" parallelOpt |> ignore 56 | 57 | queries 58 | |> Seq.map (fun query -> 59 | let nonParallelResults = Array.init n (fun _ -> run query nonParallelOpt) |> Array.skip skip 60 | let parallelResults = Array.init n (fun _ -> run query parallelOpt) |> Array.skip skip 61 | { 62 | Query = query 63 | Count = (Array.averageBy fst nonParallelResults + Array.averageBy fst parallelResults) / 2.0 |> int 64 | AverageTimeNonParallel = Array.averageBy snd nonParallelResults |> int64 65 | AverageTimeParallel = Array.averageBy snd parallelResults |> int64 66 | } 67 | ) 68 | |> Seq.iter (fun result -> 69 | printfn "%s\t%d\t%d\t%d" result.Query result.Count result.AverageTimeNonParallel result.AverageTimeParallel 70 | ) 71 | 72 | 0 -------------------------------------------------------------------------------- /tests/Profiling/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FSharp.Compiler.Service 4 | MessagePack 5 | MessagePack.FSharpExtensions -------------------------------------------------------------------------------- /tests/ProfilingLinkGenerator/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/ProfilingLinkGenerator/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace ProfilingLinkGenerator.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /tests/ProfilingLinkGenerator/ProfilingLinkGenerator.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | true 8 | ProfilingLinkGenerator 9 | true 10 | 3 11 | bin\$(Configuration) 12 | 13 | 14 | portable 15 | false 16 | 17 | 18 | portable 19 | true 20 | 21 | 22 | true 23 | portable 24 | false 25 | false 26 | DEBUG;TRACE 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/ProfilingLinkGenerator/Program.fs: -------------------------------------------------------------------------------- 1 | open FSharpApiSearch 2 | open System.Diagnostics 3 | 4 | [] 5 | let main argv = 6 | let database = Database.loadFromFile Database.databaseName 7 | 8 | let sw = Stopwatch.StartNew() 9 | 10 | for i = 0 to 50 do 11 | for apiDict in database do 12 | for api in apiDict.Api do 13 | LinkGenerator.dotNetApiBrowser "base" "view" api |> ignore 14 | 15 | printfn "%d" sw.ElapsedMilliseconds 16 | 17 | 0 -------------------------------------------------------------------------------- /tests/ProfilingLinkGenerator/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core 3 | FSharp.Compiler.Service 4 | MessagePack 5 | MessagePack.FSharpExtensions -------------------------------------------------------------------------------- /tests/SearchTestAssembly/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace SearchTestAssembly.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // アセンブリに関する一般情報は、以下の属性セットによって 8 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 9 | // これらの属性値を変更します。 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 20 | // できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 21 | // その型の ComVisible 属性を true に設定します。 22 | [] 23 | 24 | // このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります 25 | [] 26 | 27 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されます。: 28 | // 29 | // メジャー バージョン 30 | // マイナー バージョン 31 | // ビルド番号 32 | // リビジョン 33 | // 34 | // すべての値を指定するか、下に示すように '*' を使用してビルドおよびリビジョン番号を 35 | // 既定値にすることができます。: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /tests/SearchTestAssembly/SearchTestAssembly.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | true 6 | SearchTestAssembly 7 | 3 8 | true 9 | 10 | 11 | portable 12 | false 13 | 14 | 15 | portable 16 | true 17 | 18 | 19 | true 20 | portable 21 | false 22 | false 23 | DEBUG;TRACE 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/SearchTestAssembly/TestModule.fs: -------------------------------------------------------------------------------- 1 | module TestModule 2 | 3 | let f (x: int) (y: int) = 0 4 | let g (x: string) (y: string) = "" 5 | let h (x: int) (y: int) = "" 6 | 7 | type TestClass() = 8 | static member f (x: int, y: int) = 0 9 | static member g (x: string, y: string) = "" 10 | static member h (x: int, y: int) = "" -------------------------------------------------------------------------------- /tests/SearchTestAssembly/paket.references: -------------------------------------------------------------------------------- 1 | group App 2 | FSharp.Core -------------------------------------------------------------------------------- /tests/TestApiBrowserLink.fsx: -------------------------------------------------------------------------------- 1 | #r @"src\FSharpApiSearch\bin\Release\FSharpApiSearch.dll" 2 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Compiler.Service.dll" 3 | #r @"src\FSharpApiSearch\bin\Release\System.Collections.Immutable.dll" 4 | #r @"src\FSharpApiSearch\bin\Release\System.Reflection.Metadata.dll" 5 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Collections.ParallelSeq.dll" 6 | #r @"src\FSharpApiSearch\bin\Release\FParsec.dll" 7 | #r @"src\FSharpApiSearch\bin\Release\FParsecCS.dll" 8 | 9 | let database = fsi.CommandLineArgs.[1] 10 | 11 | open FSharpApiSearch 12 | open FSharpApiSearch.Printer 13 | 14 | ApiLoader.loadFromFile database 15 | |> Array.filter (fun x -> x.AssemblyName = "mscorlib" || x.AssemblyName = "System.Core") 16 | |> Array.collect (fun x -> x.Api) 17 | |> Array.iter (fun api -> 18 | match LinkGenerator.dotNetApiBrowser "https://docs.microsoft.com/en-us/dotnet/api/" "netframework-4.6.1" api with 19 | | Some link -> printfn "%s: %s" (api.Name.Print()) link 20 | | None -> printfn "%s: None" (api.Name.Print()) 21 | ) -------------------------------------------------------------------------------- /tests/TestFParsecLink.fsx: -------------------------------------------------------------------------------- 1 | #r @"src\FSharpApiSearch\bin\Release\FSharpApiSearch.dll" 2 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Compiler.Service.dll" 3 | #r @"src\FSharpApiSearch\bin\Release\System.Collections.Immutable.dll" 4 | #r @"src\FSharpApiSearch\bin\Release\System.Reflection.Metadata.dll" 5 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Collections.ParallelSeq.dll" 6 | #r @"src\FSharpApiSearch\bin\Release\FParsec.dll" 7 | #r @"src\FSharpApiSearch\bin\Release\FParsecCS.dll" 8 | 9 | let database = fsi.CommandLineArgs.[1] 10 | 11 | open FSharpApiSearch 12 | open FSharpApiSearch.Printer 13 | 14 | ApiLoader.loadFromFile database 15 | |> Array.filter (fun x -> x.AssemblyName = "FParsec") 16 | |> Array.collect (fun x -> x.Api) 17 | |> Array.choose (fun api -> 18 | match LinkGenerator.fparsec "http://www.quanttec.com/fparsec/reference/" api with 19 | | Some link -> printfn "%s: %s" (api.Name.Print()) link 20 | | None -> printfn "%s: None" (api.Name.Print()) 21 | ) -------------------------------------------------------------------------------- /tests/TestFSharpLinkExistence.fsx: -------------------------------------------------------------------------------- 1 | #r @"src\FSharpApiSearch\bin\Release\FSharpApiSearch.dll" 2 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Compiler.Service.dll" 3 | #r @"src\FSharpApiSearch\bin\Release\System.Collections.Immutable.dll" 4 | #r @"src\FSharpApiSearch\bin\Release\System.Reflection.Metadata.dll" 5 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Collections.ParallelSeq.dll" 6 | #r @"src\FSharpApiSearch\bin\Release\FParsec.dll" 7 | #r @"src\FSharpApiSearch\bin\Release\FParsecCS.dll" 8 | #r @"src\FSharpApiSearch\bin\Release\FsPickler.dll" 9 | #r @"System.Net.dll" 10 | #r @"System.Xml" 11 | #r @"System.Xml.Linq" 12 | 13 | open FSharpApiSearch 14 | open System.Web 15 | open System.IO 16 | 17 | let docDir = fsi.CommandLineArgs.[2] 18 | let fsharpDictionary = ApiLoader.loadFromFile (fsi.CommandLineArgs.[1]) |> Array.find (fun x -> x.AssemblyName = "FSharp.Core") 19 | 20 | fsharpDictionary.Api 21 | |> Seq.iter (fun api -> 22 | let apiName: string = api.Name.Print() 23 | let link = LinkGenerator.fsharp "" api |> Option.map HttpUtility.UrlDecode 24 | match link with 25 | | Some link -> 26 | let exists = 27 | try 28 | File.Exists(Path.Combine(docDir, link + ".md")) 29 | with 30 | _ -> false 31 | printfn "%s, %s, %b" apiName link exists 32 | | None -> printfn "%s, None" apiName 33 | ) -------------------------------------------------------------------------------- /tests/TestModuleFSharp.fsx: -------------------------------------------------------------------------------- 1 | #r @"src\FSharpApiSearch\bin\Release\FSharpApiSearch.dll" 2 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Compiler.Service.dll" 3 | #r @"src\FSharpApiSearch\bin\Release\System.Collections.Immutable.dll" 4 | #r @"src\FSharpApiSearch\bin\Release\System.Reflection.Metadata.dll" 5 | #r @"src\FSharpApiSearch\bin\Release\FSharp.Collections.ParallelSeq.dll" 6 | #r @"src\FSharpApiSearch\bin\Release\FParsec.dll" 7 | #r @"src\FSharpApiSearch\bin\Release\FParsecCS.dll" 8 | 9 | 10 | let database = fsi.CommandLineArgs.[1] 11 | 12 | open System.Diagnostics 13 | open FSharpApiSearch 14 | open FSharpApiSearch.Printer 15 | open System 16 | 17 | let temp = ApiLoader.loadFromFile database 18 | |> Array.filter (fun x -> x.AssemblyName = "FSharp.Core") 19 | |> Array.collect (fun x -> x.Api) 20 | let sw = Stopwatch() 21 | sw.Start() 22 | for i = 0 to 2000 do 23 | temp |> Array.choose (fun api -> LinkGenerator.fsharp "" api) |> ignore 24 | 25 | sw.Stop() 26 | let ts = sw.ElapsedMilliseconds 27 | printfn "%s" (ts.ToString()) 28 | --------------------------------------------------------------------------------