├── global.json ├── src └── RegexProvider │ ├── paket.references │ ├── paket.template │ ├── AssemblyInfo.fs │ ├── RegexProvider.fsproj │ ├── RegexExtensions.fs │ ├── TypeProviders.Helper.fs │ ├── RegexProvider.fs │ └── ProvidedTypes.fsi ├── tests └── RegexProvider.Tests │ ├── paket.references │ ├── FsUnit.fs │ ├── RegexProvider.Tests.fsproj │ ├── RegexProvider.Tests.fs │ └── RegexExtensions.Tests.fs ├── docs ├── files │ ├── img │ │ └── RegexProvider.png │ └── content │ │ ├── tips.js │ │ └── style.css ├── content │ └── index.fsx └── tools │ └── generate.fsx ├── .nuget └── packages.config ├── .travis.yml ├── appveyor.yml ├── .paket ├── paket.bootstrapper.props ├── paket.bootstrapper.proj └── Paket.Restore.targets ├── lib └── README.md ├── paket.dependencies ├── .github └── ISSUE_TEMPLATE.md ├── RegexProvider.nuspec ├── README.md ├── RegexProvider.Tests.sln ├── RELEASE_NOTES.md ├── RegexProvider.sln ├── .gitattributes ├── .gitignore ├── netfx.props └── LICENSE.txt /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "2.2.203" 4 | } 5 | } -------------------------------------------------------------------------------- /src/RegexProvider/paket.references: -------------------------------------------------------------------------------- 1 | FSharp.Core 2 | File:ProvidedTypes.fsi 3 | File:ProvidedTypes.fs 4 | -------------------------------------------------------------------------------- /tests/RegexProvider.Tests/paket.references: -------------------------------------------------------------------------------- 1 | FsUnit 2 | NUnit 3 | FSharp.Core 4 | Microsoft.NET.Test.Sdk 5 | NUnit3TestAdapter -------------------------------------------------------------------------------- /docs/files/img/RegexProvider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/FSharp.Text.RegexProvider/HEAD/docs/files/img/RegexProvider.png -------------------------------------------------------------------------------- /.nuget/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | 3 | sudo: true # use the new container-based Travis infrastructure 4 | dist: bionic 5 | mono: latest 6 | dotnet: 2.2.203 7 | script: 8 | - ./build.sh All 9 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2017 2 | init: 3 | - git config --global core.autocrlf input 4 | build_script: 5 | - cmd: build.cmd 6 | test: off 7 | version: 0.0.1.{build} 8 | artifacts: 9 | - path: bin 10 | name: bin 11 | -------------------------------------------------------------------------------- /.paket/paket.bootstrapper.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | https://www.myget.org/F/paket-netcore-as-tool/api/v2 6 | 7 | -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | This file is in the `lib` directory. 2 | 3 | Any **libraries** on which your project depends and which are **NOT managed via NuGet** should be kept **in this directory**. 4 | This typically includes custom builds of third-party software, private (i.e. to a company) codebases, and native libraries. 5 | 6 | --- 7 | NOTE: 8 | 9 | This file is a placeholder, used to preserve directory structure in Git. 10 | 11 | This file does not need to be edited. 12 | -------------------------------------------------------------------------------- /src/RegexProvider/paket.template: -------------------------------------------------------------------------------- 1 | type project 2 | authors 3 | Steffen Forkmann, David Tchepak, Sergey Tihon, Daniel Mohl, Tomas Petricek, Ryan Riley, Mauricio Scheffer, Phil Trelford, Vasily Kirichenko, Jeremie Chassaing 4 | tags 5 | F# fsharp typeproviders regex 6 | projectUrl 7 | https://fsprojects.github.io/FSharp.Text.RegexProvider/ 8 | licenseUrl 9 | https://github.com/fsprojects/FSharp.Text.RegexProvider/blob/master/LICENSE.txt 10 | copyright 11 | Copyright 2013 - 2019 12 | 13 | -------------------------------------------------------------------------------- /paket.dependencies: -------------------------------------------------------------------------------- 1 | 2 | source https://api.nuget.org/v3/index.json 3 | 4 | nuget Microsoft.NET.Test.Sdk 5 | nuget FsUnit 6 | nuget NUnit 7 | nuget NUnit.Runners 8 | nuget FSharp.Core >= 4.3.4 9 | nuget NUnit3TestAdapter version_in_path: true 10 | nuget NETStandard.Library.NETFramework 11 | 12 | github fsprojects/FSharp.TypeProviders.SDK src/ProvidedTypes.fsi 13 | github fsprojects/FSharp.TypeProviders.SDK src/ProvidedTypes.fs 14 | 15 | group docs 16 | frameworks: netstandard2.0 17 | generate_load_scripts: true 18 | source https://api.nuget.org/v3/index.json 19 | nuget FSharp.Core 20 | nuget FSharp.Literate 21 | nuget Fable.React 22 | nuget FSharp.Compiler.Tools 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | Please provide a succinct description of your issue. 4 | 5 | ### Repro steps 6 | 7 | Please provide the steps required to reproduce the problem 8 | 9 | 1. Step A 10 | 11 | 2. Step B 12 | 13 | ### Expected behavior 14 | 15 | Please provide a description of the behavior you expect. 16 | 17 | ### Actual behavior 18 | 19 | Please provide a description of the actual behavior you observe. 20 | 21 | ### Known workarounds 22 | 23 | Please provide a description of any known workarounds. 24 | 25 | ### Related information 26 | 27 | * Operating system 28 | * Branch 29 | * .NET Runtime, CoreCLR or Mono Version 30 | * Performance information, links to performance testing scripts 31 | -------------------------------------------------------------------------------- /src/RegexProvider/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | // Auto-Generated by FAKE; do not edit 2 | namespace System 3 | open System.Reflection 4 | 5 | [] 6 | [] 7 | [] 8 | [] 9 | [] 10 | do () 11 | 12 | module internal AssemblyVersionInformation = 13 | let [] AssemblyTitle = "FSharp.Text.RegexProvider" 14 | let [] AssemblyProduct = "FSharp.Text.RegexProvider" 15 | let [] AssemblyDescription = "A type provider for regular expressions." 16 | let [] AssemblyVersion = "2.1.0" 17 | let [] AssemblyFileVersion = "2.1.0" 18 | -------------------------------------------------------------------------------- /RegexProvider.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @project@ 5 | @build.number@ 6 | @authors@ 7 | @authors@ 8 | http://github.com/fsprojects/FSharp.Text.RegexProvider/blob/master/LICENSE 9 | http://fsprojects.github.com/FSharp.Text.RegexProvider 10 | false 11 | @summary@ 12 | @description@ 13 | @releaseNotes@ 14 | Copyright 2013 15 | @tags@ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RegexProvider [](https://www.nuget.org/packages/FSharp.Text.RegexProvider/) 2 | ============= 3 | 4 | The RegexProvider project contains a type providers for regular expressions. Documentation available here. 5 | 6 | ## Building 7 | 8 | * Mono: Run *build.sh* [](https://travis-ci.org/fsprojects/FSharp.Text.RegexProvider) 9 | * Windows: Run *build.cmd* 10 | 11 | ## Maintainer(s) 12 | 13 | - [@dtchepak](https://github.com/dtchepak) 14 | - [@forki](https://github.com/forki) 15 | - [@vasily-kirichenko](https://github.com/vasily-kirichenko) 16 | 17 | The default maintainer account for projects under "fsprojects" is [@fsprojectsgit](https://github.com/fsprojectsgit) - F# Community Project Incubation Space (repo management) 18 | -------------------------------------------------------------------------------- /tests/RegexProvider.Tests/FsUnit.fs: -------------------------------------------------------------------------------- 1 | module FsUnit 2 | open NUnit.Framework 3 | open NUnit.Framework.Constraints 4 | 5 | let should (f : 'a -> #Constraint) x (y : obj) = 6 | let c = f x 7 | let y = 8 | match y with 9 | | :? (unit -> unit) -> box (new TestDelegate(y :?> unit -> unit)) 10 | | _ -> y 11 | Assert.That(y, c) 12 | 13 | let equal x = new EqualConstraint(x) 14 | 15 | // like "should equal", but validates same-type 16 | let shouldEqual (x: 'a) (y: 'a) = Assert.AreEqual(x, y, sprintf "Expected: %A\nActual: %A" x y) 17 | 18 | let contain x = new ContainsConstraint(x) 19 | 20 | let haveLength n = Has.Length.EqualTo(n) 21 | 22 | let haveCount n = Has.Count.EqualTo(n) 23 | 24 | let be = id 25 | 26 | let Null = new NullConstraint() 27 | 28 | let Empty = new EmptyConstraint() 29 | 30 | let EmptyString = new EmptyStringConstraint() 31 | 32 | let True = new TrueConstraint() 33 | 34 | let False = new FalseConstraint() 35 | 36 | let sameAs x = new SameAsConstraint(x) 37 | 38 | let throw = Throws.TypeOf 39 | -------------------------------------------------------------------------------- /tests/RegexProvider.Tests/RegexProvider.Tests.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Library 5 | netcoreapp2.2;net461 6 | true 7 | 8 | 9 | false 10 | 11 | 12 | true 13 | 14 | 15 | 16 | RegexProvider.fsproj 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/files/content/tips.js: -------------------------------------------------------------------------------- 1 | var currentTip = null; 2 | var currentTipElement = null; 3 | 4 | function hideTip(evt, name, unique) 5 | { 6 | var el = document.getElementById(name); 7 | el.style.display = "none"; 8 | currentTip = null; 9 | } 10 | 11 | function findPos(obj) 12 | { 13 | // no idea why, but it behaves differently in webbrowser component 14 | if (window.location.search == "?inapp") 15 | return [obj.offsetLeft + 10, obj.offsetTop + 30]; 16 | 17 | var curleft = 0; 18 | var curtop = obj.offsetHeight; 19 | while (obj) 20 | { 21 | curleft += obj.offsetLeft; 22 | curtop += obj.offsetTop; 23 | obj = obj.offsetParent; 24 | }; 25 | return [curleft, curtop]; 26 | } 27 | 28 | function hideUsingEsc(e) 29 | { 30 | if (!e) { e = event; } 31 | hideTip(e, currentTipElement, currentTip); 32 | } 33 | 34 | function showTip(evt, name, unique, owner) 35 | { 36 | document.onkeydown = hideUsingEsc; 37 | if (currentTip == unique) return; 38 | currentTip = unique; 39 | currentTipElement = name; 40 | 41 | var pos = findPos(owner ? owner : (evt.srcElement ? evt.srcElement : evt.target)); 42 | var posx = pos[0]; 43 | var posy = pos[1]; 44 | 45 | var el = document.getElementById(name); 46 | var parent = (document.documentElement == null) ? document.body : document.documentElement; 47 | el.style.position = "absolute"; 48 | el.style.left = posx + "px"; 49 | el.style.top = posy + "px"; 50 | el.style.display = "block"; 51 | } -------------------------------------------------------------------------------- /docs/files/content/style.css: -------------------------------------------------------------------------------- 1 | /* identifier */ 2 | span.i { color:#000000; } 3 | /* comment */ 4 | span.c { color:#008000; } 5 | /* inactive code */ 6 | span.inactive { color:#808080; } 7 | /* keywords */ 8 | span.k { color:#000080; } 9 | /* numbers */ 10 | span.n { color:#008000; } 11 | /* operators */ 12 | span.o { color:#800080; } 13 | /* preprocessor */ 14 | span.prep { color:#800080; } 15 | /* string */ 16 | span.s { color:#808000; } 17 | /* line number */ 18 | span.l { color:#80b0b0; } 19 | /* fsi output */ 20 | span.fsi { font-style:italic; color:#606060; } 21 | /* omitted */ 22 | span.omitted { 23 | border:solid 1px #d8d8d8; 24 | color:#808080; 25 | padding:0px 0px 1px 0px; 26 | background:#fafafa; 27 | } 28 | span.cerr { 29 | background:url(tilde.png) repeat-x left bottom; 30 | } 31 | 32 | div.tip 33 | { 34 | font:8pt calibri; 35 | padding:3px; 36 | border:1px solid #606060; 37 | background:#ffffd0; 38 | display:none; 39 | pointer-events:none; 40 | } 41 | 42 | h2 43 | { 44 | font:bold 16pt 'calibri'; 45 | } 46 | 47 | pre a.fssniplink 48 | { 49 | font:bold 7.5pt calibry, arial, verdana; 50 | position:absolute; 51 | bottom:0.3em; 52 | right:0.3em; 53 | color:#a8a8a8; 54 | } 55 | 56 | /* Optionally, also configure how the PRE element and TABLE.PRE look */ 57 | table.pre pre { 58 | padding:0px; 59 | margin:0px; 60 | border-style:none; 61 | } 62 | 63 | pre, table.pre td { 64 | padding:9.5px; 65 | background:#f5f5f5; 66 | border:solid 1px black; 67 | border-radius:4px; 68 | border-color:rgba(0,0,0,0.15); 69 | margin:0px 0px 10px 0px; 70 | } 71 | 72 | table.pre td.lines { 73 | border-top-right-radius:0px; 74 | border-bottom-right-radius:0px; 75 | border-right-style: none; 76 | padding-right:0px; 77 | } 78 | table.pre td.snippet { 79 | border-top-left-radius:0px; 80 | border-bottom-left-radius:0px; 81 | border-left-style: none; 82 | padding-left:4px; 83 | } 84 | 85 | code, pre, pre code { 86 | font-family:9pt consolas, monaco,'Lucida Console',monospace; 87 | line-height:13pt; 88 | } -------------------------------------------------------------------------------- /RegexProvider.Tests.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{11B65369-DBF0-40E2-B6C9-88DBEA104EAC}" 7 | EndProject 8 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "RegexProvider.Tests", "tests\RegexProvider.Tests\RegexProvider.Tests.fsproj", "{DB11FC48-02B7-48B3-B471-2387E8D53EF5}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Debug|x64.ActiveCfg = Debug|Any CPU 26 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Debug|x64.Build.0 = Debug|Any CPU 27 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Debug|x86.ActiveCfg = Debug|Any CPU 28 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Debug|x86.Build.0 = Debug|Any CPU 29 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Release|x64.ActiveCfg = Release|Any CPU 32 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Release|x64.Build.0 = Release|Any CPU 33 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Release|x86.ActiveCfg = Release|Any CPU 34 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5}.Release|x86.Build.0 = Release|Any CPU 35 | EndGlobalSection 36 | GlobalSection(NestedProjects) = preSolution 37 | {DB11FC48-02B7-48B3-B471-2387E8D53EF5} = {11B65369-DBF0-40E2-B6C9-88DBEA104EAC} 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | #### 2.1.0 - 19.06.2019 2 | * Add TryTypedMatch that returns an option - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/20 3 | * Add extension methods on Group to easily and safely convert to primitive types 4 | * Add TypedReplace with typed evaluator - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/5 5 | * Make type set local to provider instance to have consitent type names over rebuilds 6 | * Add overload for Match and Matches that takes starting position and number of occurence - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/19 7 | * Add ctor overload that takes a timeout 8 | 9 | #### 2.0.2 - 17.06.2019 10 | * Fix Nuget page is missing metadata - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/26 11 | * Https documentation page 12 | 13 | #### 2.0.1 - 12.06.2019 14 | * FIx FSharp.Core dependency version in nuget 15 | 16 | #### 2.0.0 - 12.06.2019 17 | * Update to net461 and netstandard2.0 - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/18 18 | 19 | #### 1.0.0 - 07.07.2016 20 | * Added a `Typed` prefix to generated methods - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/16 21 | 22 | #### 0.0.7 - 30.05.2015 23 | * Renamed to FSharp.Text.RegexProvider and updated links to project site - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/11 24 | 25 | #### 0.0.6 - 30.05.2015 26 | * Renamed to FSharp.Text.RegexProvider - https://github.com/fsprojects/FSharp.Text.RegexProvider/issues/11 27 | 28 | #### 0.0.5 - 22.04.2015 29 | * Add constructor overload that takes regex options - https://github.com/fsprojects/RegexProvider/issues/10 30 | 31 | #### 0.0.4 - 27.11.2014 32 | * Fix intellisense hang due to race condition - https://github.com/fsprojects/RegexProvider/issues/8 33 | 34 | #### 0.0.3 - 28.09.2014 35 | * Return provided Match type from Match.NextMatch() - https://github.com/fsprojects/RegexProvider/issues/4 36 | 37 | #### 0.0.2 - 23.02.2014 38 | * Changing project to target NET40 (instead of NET45). 39 | 40 | #### 0.0.1 - 23.02.2014 41 | * Adding Matches method 42 | 43 | #### 0.0.1-alpha - 21.02.2014 44 | * Initial release of RegexProvider 45 | -------------------------------------------------------------------------------- /RegexProvider.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29001.49 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{FC8DDDEE-CF41-4EC2-ADA8-C202E7423FF1}" 7 | ProjectSection(SolutionItems) = preProject 8 | paket.dependencies = paket.dependencies 9 | EndProjectSection 10 | EndProject 11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{A6A6AF7D-D6E3-442D-9B1E-58CC91879BE1}" 12 | EndProject 13 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "RegexProvider", "src\RegexProvider\RegexProvider.fsproj", "{7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}" 14 | EndProject 15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{BF60BC93-E09B-4E5F-9D85-95A519479D54}" 16 | ProjectSection(SolutionItems) = preProject 17 | build.fsx = build.fsx 18 | README.md = README.md 19 | nuget\RegexProvider.nuspec = nuget\RegexProvider.nuspec 20 | RELEASE_NOTES.md = RELEASE_NOTES.md 21 | EndProjectSection 22 | EndProject 23 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{83F16175-43B1-4C90-A1EE-8E351C33435D}" 24 | ProjectSection(SolutionItems) = preProject 25 | docs\tools\generate.fsx = docs\tools\generate.fsx 26 | EndProjectSection 27 | EndProject 28 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{8E6D5255-776D-4B61-85F9-73C37AA1FB9A}" 29 | ProjectSection(SolutionItems) = preProject 30 | docs\content\index.fsx = docs\content\index.fsx 31 | EndProjectSection 32 | EndProject 33 | Global 34 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 35 | Debug|Any CPU = Debug|Any CPU 36 | Release|Any CPU = Release|Any CPU 37 | EndGlobalSection 38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 39 | {7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}.Release|Any CPU.Build.0 = Release|Any CPU 43 | EndGlobalSection 44 | GlobalSection(SolutionProperties) = preSolution 45 | HideSolutionNode = FALSE 46 | EndGlobalSection 47 | GlobalSection(NestedProjects) = preSolution 48 | {83F16175-43B1-4C90-A1EE-8E351C33435D} = {A6A6AF7D-D6E3-442D-9B1E-58CC91879BE1} 49 | {8E6D5255-776D-4B61-85F9-73C37AA1FB9A} = {A6A6AF7D-D6E3-442D-9B1E-58CC91879BE1} 50 | EndGlobalSection 51 | GlobalSection(ExtensibilityGlobals) = postSolution 52 | SolutionGuid = {BE740DCC-41BC-497F-9E95-6B4AA184FD54} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /src/RegexProvider/RegexProvider.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library 6 | FSharp.Text.RegexProvider 7 | netstandard2.0;net461 8 | true 9 | true 10 | true 11 | ..\..\bin\$(TargetFramework)\FSharp.Text.RegexProvider.XML 12 | true 13 | 14 | 15 | 16 | 17 | True 18 | paket-files/ProvidedTypes.fsi 19 | 20 | 21 | True 22 | paket-files/ProvidedTypes.fs 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | PreserveNewest 36 | 37 | 38 | PreserveNewest 39 | 40 | 41 | PreserveNewest 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.paket/paket.bootstrapper.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(MSBuildThisFileDirectory.TrimEnd('\\').TrimEnd('/')) 7 | 8 | $(RepoRoot)\paket.bootstrapper.exe 9 | $(RepoRoot)/paket.bootstrapper 10 | $(RepoRoot)\paket.exe 11 | $(RepoRoot)/paket 12 | 13 | 14 | 15 | 16 | 17 | dotnet tool install paket.bootstrapper --tool-path "$(RepoRoot)" 18 | $(InstallBootstrapperCommand) --version "[$(PaketBootstrapperVersion)]" 19 | $(InstallBootstrapperCommand) --add-source "$(PaketBootstrapperFeed)" 20 | $(InstallBootstrapperCommand) $(InstallBootstrapperOtherArgs)" 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | $(PaketBootstrapperExe) --as-tool --output-dir=$(RepoRoot) 29 | $(RunBootstrapperCommand) --config-file=$(RepoRoot)/paket.bootstrapper.exe.config 30 | $(RunBootstrapperCommand) $(RunBootstrapperOtherArgs) 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /.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 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # Enable nuget.exe in the .nuget folder (though normally executables are not tracked) 99 | !.nuget/NuGet.exe 100 | 101 | # Windows Azure Build Output 102 | csx 103 | *.build.csdef 104 | 105 | # Windows Store app package directory 106 | AppPackages/ 107 | 108 | # Others 109 | sql/ 110 | *.Cache 111 | ClientBin/ 112 | [Ss]tyle[Cc]op.* 113 | ~$* 114 | *~ 115 | *.dbmdl 116 | *.[Pp]ublish.xml 117 | *.pfx 118 | *.publishsettings 119 | 120 | # RIA/Silverlight projects 121 | Generated_Code/ 122 | 123 | # Backup & report files from converting an old project file to a newer 124 | # Visual Studio version. Backup files are not needed, because we have git ;-) 125 | _UpgradeReport_Files/ 126 | Backup*/ 127 | UpgradeLog*.XML 128 | UpgradeLog*.htm 129 | 130 | # SQL Server files 131 | App_Data/*.mdf 132 | App_Data/*.ldf 133 | 134 | 135 | #LightSwitch generated files 136 | GeneratedArtifacts/ 137 | _Pvt_Extensions/ 138 | ModelManifest.xml 139 | 140 | # ========================= 141 | # Windows detritus 142 | # ========================= 143 | 144 | # Windows image file caches 145 | Thumbs.db 146 | ehthumbs.db 147 | 148 | # Folder config file 149 | Desktop.ini 150 | 151 | # Recycle Bin used on file shares 152 | $RECYCLE.BIN/ 153 | 154 | # Mac desktop service store files 155 | .DS_Store 156 | 157 | # =================================================== 158 | # Exclude F# project specific directories and files 159 | # =================================================== 160 | 161 | # NuGet Packages Directory 162 | packages/ 163 | 164 | # Generated documentation folder 165 | docs/output/ 166 | 167 | # Temp folder used for publishing docs 168 | temp/ 169 | 170 | # Test results produced by build 171 | TestResults.xml 172 | release.cmd 173 | nuget/ 174 | 175 | # Nuget outputs 176 | nuget/*.nupkg 177 | .paket/paket.exe 178 | docs/content/license.md 179 | docs/content/release-notes.md 180 | 181 | .fake/ 182 | .ionide/ 183 | .paket/load/ 184 | .vs/ 185 | .paket/paket.bootstrapper.exe 186 | .paket/.store/ 187 | paket-files/ 188 | **/[Oo]bj/ 189 | **/[Bb]in/ 190 | .tools/ 191 | .paket/paket 192 | .paket/paket.bootstrapper -------------------------------------------------------------------------------- /netfx.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | /Library/Frameworks/Mono.framework/Versions/Current/lib/mono 11 | /usr/lib/mono 12 | /usr/local/lib/mono 13 | 14 | 15 | $(BaseFrameworkPathOverrideForMono)/4.5-api 16 | $(BaseFrameworkPathOverrideForMono)/4.5.1-api 17 | $(BaseFrameworkPathOverrideForMono)/4.5.2-api 18 | $(BaseFrameworkPathOverrideForMono)/4.6-api 19 | $(BaseFrameworkPathOverrideForMono)/4.6.1-api 20 | $(BaseFrameworkPathOverrideForMono)/4.6.2-api 21 | $(BaseFrameworkPathOverrideForMono)/4.7-api 22 | $(BaseFrameworkPathOverrideForMono)/4.7.1-api 23 | true 24 | 25 | 26 | $(FrameworkPathOverride)/Facades;$(AssemblySearchPaths) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/RegexProvider/RegexExtensions.fs: -------------------------------------------------------------------------------- 1 | module FSharp.Text.RegexExtensions 2 | 3 | open System 4 | open System.Text.RegularExpressions 5 | open System.Globalization 6 | 7 | let inline private tryParseNumber (g:Group) style : ^t option = 8 | if g.Success then 9 | let mutable value = Unchecked.defaultof< ^t > 10 | if (^t : (static member TryParse: string * NumberStyles * CultureInfo * ^t byref -> bool ) (g.Value, style, CultureInfo.InvariantCulture,&value)) then 11 | Some value 12 | else 13 | None 14 | else 15 | None 16 | 17 | let inline private tryParseDate (g:Group) style : ^t option = 18 | if g.Success then 19 | let mutable value = Unchecked.defaultof< ^t > 20 | if (^t : (static member TryParse: string * CultureInfo * DateTimeStyles * ^t byref -> bool ) (g.Value, CultureInfo.InvariantCulture, style ,&value)) then 21 | Some value 22 | else 23 | None 24 | else 25 | None 26 | 27 | 28 | type Group with 29 | member this.TryValue = 30 | if this.Success then Some this.Value else None 31 | member this.AsInt = int this.Value 32 | member this.AsUInt32 = uint32 this.Value 33 | member this.AsInt64 = int64 this.Value 34 | member this.AsUInt64 = uint64 this.Value 35 | member this.AsInt16 = int16 this.Value 36 | member this.AsUInt16 = uint16 this.Value 37 | member this.AsByte = byte this.Value 38 | member this.AsSByte = sbyte this.Value 39 | member this.AsDecimal = decimal this.Value 40 | member this.AsFloat = float this.Value 41 | member this.AsSingle = single this.Value 42 | member this.AsDateTime style = DateTime.Parse(this.Value, CultureInfo.InvariantCulture, style) 43 | member this.AsDateTimeOffset style = DateTimeOffset.Parse(this.Value, CultureInfo.InvariantCulture, style) 44 | member this.AsTimeSpan = TimeSpan.Parse(this.Value, CultureInfo.InvariantCulture) 45 | member this.AsBool = Boolean.Parse(this.Value) 46 | member this.AsChar = char this.Value 47 | 48 | member this.TryAsInt : int option = tryParseNumber this NumberStyles.Integer 49 | member this.TryAsUInt32 : uint32 option = tryParseNumber this NumberStyles.Integer 50 | member this.TryAsInt64 : int64 option = tryParseNumber this NumberStyles.Integer 51 | member this.TryAsUInt64 : uint64 option = tryParseNumber this NumberStyles.Integer 52 | member this.TryAsInt16 : int16 option = tryParseNumber this NumberStyles.Integer 53 | member this.TryAsUInt16 : uint16 option = tryParseNumber this NumberStyles.Integer 54 | member this.TryAsByte : byte option = tryParseNumber this NumberStyles.Integer 55 | member this.TryAsSByte : sbyte option= tryParseNumber this NumberStyles.Integer 56 | member this.TryAsDecimal : decimal option = tryParseNumber this NumberStyles.Number 57 | member this.TryAsFloat : float option = tryParseNumber this NumberStyles.Float 58 | member this.TryAsSingle : single option = tryParseNumber this NumberStyles.Float 59 | member this.TryAsDateTime style : DateTime option = tryParseDate this style 60 | member this.TryAsDateTimeOffset style : DateTimeOffset option = tryParseDate this style 61 | member this.TryAsTimeSpan : TimeSpan option = 62 | if this.Success then 63 | match TimeSpan.TryParse(this.Value, CultureInfo.InvariantCulture) with 64 | | true, value -> Some value 65 | | false, _ -> None 66 | else 67 | None 68 | member this.TryAsBool : bool option = 69 | if this.Success then 70 | match Boolean.TryParse(this.Value) with 71 | | true, value -> Some value 72 | | false, _ -> None 73 | else 74 | None 75 | member this.TryAsChar : char option = 76 | if this.Success then 77 | match Char.TryParse(this.Value) with 78 | | true, value -> Some value 79 | | false, _ -> None 80 | else 81 | None 82 | 83 | -------------------------------------------------------------------------------- /src/RegexProvider/TypeProviders.Helper.fs: -------------------------------------------------------------------------------- 1 | /// Starting to implement some helpers on top of ProvidedTypes API 2 | namespace FSharp.Text.RegexProvider 3 | 4 | module internal Helper = 5 | open System 6 | open System.IO 7 | open ProviderImplementation.ProvidedTypes 8 | 9 | type Context (onChanged : unit -> unit) = 10 | let disposingEvent = Event<_>() 11 | let lastChanged = ref (DateTime.Now.AddSeconds -1.0) 12 | let sync = obj() 13 | 14 | let trigger() = 15 | let shouldTrigger = lock sync (fun _ -> 16 | match !lastChanged with 17 | | time when DateTime.Now - time <= TimeSpan.FromSeconds 1. -> false 18 | | _ -> 19 | lastChanged := DateTime.Now 20 | true 21 | ) 22 | if shouldTrigger then onChanged() 23 | 24 | member this.Disposing: IEvent = disposingEvent.Publish 25 | member this.Trigger = trigger 26 | interface IDisposable with 27 | member x.Dispose() = disposingEvent.Trigger() 28 | 29 | // Active patterns & operators for parsing strings 30 | let (@?) (s:string) i = if i >= s.Length then None else Some s.[i] 31 | 32 | let inline satisfies predicate (charOption:option) = 33 | match charOption with 34 | | Some c when predicate c -> charOption 35 | | _ -> None 36 | 37 | let (|EOF|_|) = function 38 | | Some _ -> None 39 | | _ -> Some () 40 | 41 | let (|LetterDigit|_|) = satisfies Char.IsLetterOrDigit 42 | let (|Upper|_|) = satisfies Char.IsUpper 43 | let (|Lower|_|) = satisfies Char.IsLower 44 | 45 | /// Turns a string into a nice PascalCase identifier 46 | let niceName (set:System.Collections.Concurrent.ConcurrentDictionary<_, unit>) = 47 | fun (s: string) -> 48 | if s = s.ToUpper() then s else 49 | // Starting to parse a new segment 50 | let rec restart i = seq { 51 | match s @? i with 52 | | EOF -> () 53 | | LetterDigit _ & Upper _ -> yield! upperStart i (i + 1) 54 | | LetterDigit _ -> yield! consume i false (i + 1) 55 | | _ -> yield! restart (i + 1) } 56 | 57 | // Parsed first upper case letter, continue either all lower or all upper 58 | and upperStart from i = seq { 59 | match s @? i with 60 | | Upper _ -> yield! consume from true (i + 1) 61 | | Lower _ -> yield! consume from false (i + 1) 62 | | _ -> yield! restart (i + 1) } 63 | // Consume are letters of the same kind (either all lower or all upper) 64 | and consume from takeUpper i = seq { 65 | match s @? i with 66 | | Lower _ when not takeUpper -> yield! consume from takeUpper (i + 1) 67 | | Upper _ when takeUpper -> yield! consume from takeUpper (i + 1) 68 | | _ -> 69 | yield from, i 70 | yield! restart i } 71 | 72 | // Split string into segments and turn them to PascalCase 73 | let mutable name = 74 | seq { for i1, i2 in restart 0 do 75 | let sub = s.Substring(i1, i2 - i1) 76 | if Seq.forall Char.IsLetterOrDigit sub then 77 | yield sub.[0].ToString().ToUpper() + sub.ToLower().Substring(1) } 78 | |> String.concat "" 79 | 80 | while set.ContainsKey name do 81 | let mutable lastLetterPos = String.length name - 1 82 | while Char.IsDigit name.[lastLetterPos] && lastLetterPos > 0 do 83 | lastLetterPos <- lastLetterPos - 1 84 | if lastLetterPos = name.Length - 1 then 85 | name <- name + "2" 86 | elif lastLetterPos = 0 then 87 | name <- (UInt64.Parse name + 1UL).ToString() 88 | else 89 | let number = name.Substring(lastLetterPos + 1) 90 | name <- name.Substring(0, lastLetterPos + 1) + (UInt64.Parse number + 1UL).ToString() 91 | set.TryAdd (name,()) |> ignore 92 | name 93 | 94 | 95 | let findConfigFile resolutionFolder configFileName = 96 | if Path.IsPathRooted configFileName then 97 | configFileName 98 | else 99 | Path.Combine(resolutionFolder, configFileName) 100 | 101 | let erasedType<'T> assemblyName rootNamespace typeName hideObjectMethods = 102 | ProvidedTypeDefinition(assemblyName, rootNamespace, typeName, Some(typeof<'T>), hideObjectMethods = hideObjectMethods) 103 | 104 | let createTypeSet() = System.Collections.Concurrent.ConcurrentDictionary<_, unit>() 105 | 106 | let runtimeType<'T> typeName hideObjectMethods typeSet = ProvidedTypeDefinition(niceName typeSet typeName, Some typeof<'T>, hideObjectMethods=hideObjectMethods) 107 | 108 | let seqType ty = typedefof>.MakeGenericType[| ty |] 109 | let listType ty = typedefof>.MakeGenericType[| ty |] 110 | let optionType ty = typedefof>.MakeGenericType[| ty |] 111 | let funType ty tr = typedefof<_ -> _>.MakeGenericType[| ty; tr |] 112 | 113 | // Get the assembly and namespace used to house the provided types 114 | let thisAssembly = System.Reflection.Assembly.GetExecutingAssembly() 115 | let rootNamespace = "FSharp.Text.RegexProvider" 116 | let missingValue = "@@@missingValue###" -------------------------------------------------------------------------------- /tests/RegexProvider.Tests/RegexProvider.Tests.fs: -------------------------------------------------------------------------------- 1 | module FSharp.Text.RegexProvider.Tests.RegexProviderTests 2 | 3 | open NUnit.Framework 4 | open System.Text.RegularExpressions 5 | open FSharp.Text.RegexProvider 6 | open FsUnit 7 | 8 | type PhoneRegex = Regex< @"(?^\d{3})-(?\d{3}-\d{4}$)", noMethodPrefix = true > 9 | 10 | [] 11 | let ``Can call typed IsMatch function``() = 12 | PhoneRegex.IsMatch "425-123-2345" 13 | |> should equal true 14 | 15 | [] 16 | let ``The default regex options are None``() = 17 | PhoneRegex().Options |> should equal RegexOptions.None 18 | 19 | [] 20 | let ``The regex options are passed``() = 21 | PhoneRegex(RegexOptions.Compiled).Options |> should equal RegexOptions.Compiled 22 | 23 | [] 24 | let ``The match timeout is passed``() = 25 | PhoneRegex(RegexOptions.Compiled, System.TimeSpan.FromSeconds 2.).MatchTimeout 26 | |> should equal (System.TimeSpan.FromSeconds 2.) 27 | 28 | [] 29 | let ``Can call typed CompleteMatch function``() = 30 | PhoneRegex().Match("425-123-2345").CompleteMatch.Value 31 | |> should equal "425-123-2345" 32 | 33 | [] 34 | let ``Can return AreaCode in simple phone number``() = 35 | PhoneRegex().Match("425-123-2345").AreaCode.Value 36 | |> should equal "425" 37 | 38 | [] 39 | let ``Can return PhoneNumber property in simple phone number``() = 40 | PhoneRegex().Match("425-123-2345").PhoneNumber.Value 41 | |> should equal "123-2345" 42 | 43 | type MultiplePhoneRegex = Regex< @"\b(?\d{3})-(?\d{3}-\d{4})\b", noMethodPrefix = true > 44 | [] 45 | let ``Can return multiple matches``() = 46 | MultiplePhoneRegex().Matches("425-123-2345, 426-123-2346, 427-123-2347") 47 | |> Seq.map (fun x -> x.AreaCode.Value) 48 | |> List.ofSeq 49 | |> should equal ["425"; "426"; "427"] 50 | 51 | [] 52 | let ``Can return multiple matches from starting positiong``() = 53 | MultiplePhoneRegex().Matches("425-123-2345, 426-123-2346, 427-123-2347", 13 ) 54 | |> Seq.map (fun x -> x.AreaCode.Value) 55 | |> List.ofSeq 56 | |> should equal ["426"; "427"] 57 | 58 | [] 59 | let ``Can return next matches``() = 60 | let m = MultiplePhoneRegex().Match("425-123-2345, 426-123-2346, 427-123-2347") 61 | m.AreaCode.Value 62 | |> should equal "425" 63 | 64 | let m' = m.NextMatch() 65 | m'.AreaCode.Value 66 | |> should equal "426" 67 | 68 | type WordRegex = Regex< @"(?\w+)" > 69 | 70 | [] 71 | let ``Can call typed TypedMatches function``() = 72 | let matcher = WordRegex().TypedMatches 73 | let matches = matcher @"The fox jumps over the lazy dog" 74 | let words = matches |> Seq.map (fun m -> m.Word.Value) 75 | words |> should equal ["The";"fox";"jumps";"over";"the";"lazy";"dog"] 76 | 77 | let inline extractWords regex text = 78 | let matches: ^m seq = (^r: (member TypedMatches: string -> ^m seq) (regex, text)) 79 | let getGroup m = (^m: (member get_Word: unit -> System.Text.RegularExpressions.Group) m) 80 | matches |> Seq.map (fun m -> (getGroup m).Value) 81 | 82 | type WordRegex2 = Regex< @"(?fox|dog)" > 83 | 84 | [] 85 | let ``Inline function can be called on several typed regexes``() = 86 | let input = @"The fox jumps over the lazy dog" 87 | let wordExtractor1 = extractWords (WordRegex()) 88 | let words1 = wordExtractor1 input 89 | words1 |> should equal ["The";"fox";"jumps";"over";"the";"lazy";"dog"] 90 | 91 | let wordExtractor2 = extractWords (WordRegex2()) 92 | let words2 = wordExtractor2 input 93 | words2 |> should equal ["fox";"dog"] 94 | 95 | 96 | [] 97 | let ``Can return PhoneNumber property in simple phone number with TryMatch``() = 98 | PhoneRegex().TryMatch("425-123-2345") 99 | |> Option.map (fun p -> p.PhoneNumber.Value) 100 | |> should equal (Some "123-2345") 101 | 102 | 103 | [] 104 | let ``Can return None with TryMatch``() = 105 | PhoneRegex().TryMatch("425x123x2345") 106 | |> Option.map (fun p -> p.PhoneNumber.Value) 107 | |> shouldEqual None 108 | 109 | [] 110 | let ``Can match starting at position`` = 111 | let word = WordRegex().TypedMatch("The fox jumps over the lazy dog", 3) 112 | word.Word.Value 113 | |> should equal ("fox") 114 | 115 | 116 | [] 117 | let ``Can match starting at position with given length`` = 118 | let word = WordRegex().TypedMatch("The fox jumps over the lazy dog", 3,3) 119 | word.Word.Value 120 | |> should equal ("fo") 121 | 122 | 123 | [] 124 | let ``Can try match starting at position`` = 125 | let word = 126 | WordRegex().TryTypedMatch("The fox jumps over the lazy dog", 3) 127 | |> Option.map (fun m -> m.Word.Value) 128 | 129 | word 130 | |> should equal (Some "fox") 131 | 132 | 133 | [] 134 | let ``Can try match starting at position with given length`` = 135 | let word = 136 | WordRegex().TryTypedMatch("The fox jumps over the lazy dog", 3,3) 137 | |> Option.map (fun m -> m.Word.Value) 138 | 139 | word 140 | |> should equal (Some "fo") 141 | 142 | [] 143 | let ``Replace can take typed match``() = 144 | let input = @"The fox jumps over the lazy dog" 145 | WordRegex().TypedReplace(input, fun m -> string m.Word.Value.Length) 146 | |> shouldEqual "3 3 5 4 3 4 3" 147 | 148 | [] 149 | let ``Replace can take typed match with specified count``() = 150 | let input = @"The fox jumps over the lazy dog" 151 | WordRegex().TypedReplace(input, (fun m -> string m.Word.Value.Length), 3) 152 | |> shouldEqual "3 3 5 over the lazy dog" 153 | 154 | 155 | [] 156 | let ``Replace can take typed match with specified count and starting position``() = 157 | let input = @"The fox jumps over the lazy dog" 158 | WordRegex().TypedReplace(input, (fun m -> string m.Word.Value.Length), 3, 4) 159 | |> shouldEqual "The 3 5 4 the lazy dog" 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs/content/index.fsx: -------------------------------------------------------------------------------- 1 | (*** hide ***) 2 | #I "../../bin/netstandard2.0" 3 | 4 | (** 5 | FSharp.Text.RegexProvider 6 | =========================== 7 | 8 | The FSharp.Text.RegexProvider project contains a type provider for regular expressions. 9 | 10 | 11 | 12 | 13 | 14 | The library can be installed from NuGet: 15 | PM> Install-Package FSharp.Text.RegexProvider 16 | 17 | 18 | 19 | 20 | 21 | Example 22 | ------- 23 | 24 | This example demonstrates the use of the type provider: 25 | 26 | *) 27 | // reference the type provider dll 28 | #r "FSharp.Text.RegexProvider.dll" 29 | open System.Globalization 30 | open FSharp.Text.RegexProvider 31 | 32 | // Let the type provider do its work 33 | type PhoneRegex = Regex< @"(?^\d{3})-(?\d{3}-\d{4}$)" > 34 | 35 | 36 | // now you have typed access to the regex groups and you can browse it via Intellisense 37 | PhoneRegex().TypedMatch("425-123-2345").AreaCode.Value 38 | 39 | // [fsi:val it : string = "425"] 40 | 41 | // you can also get an option for simpler handling in case the rege doesn't match 42 | match PhoneRegex().TryTypedMatch("425-123-2345") with 43 | | Some m -> printfn "Phone number is %s" m.PhoneNumber.Value 44 | | None -> printfn "Phone number unavailable" 45 | 46 | (** 47 | 48 |  49 | 50 | Note that since version 1.0, generated methods are prefixed by `Typed` by default. 51 | You can disable this behaviour using the parameter `noMethodPrefix`: 52 | *) 53 | 54 | type MultiplePhoneRegex = Regex< @"\b(?\d{3})-(?\d{3}-\d{4})\b", noMethodPrefix = true > 55 | 56 | // now the generated types are just added as an overload of the existing method name on the `Regex` type 57 | MultiplePhoneRegex().Matches("425-123-2345, 426-123-2346, 427-123-2347") 58 | |> Seq.map (fun x -> x.AreaCode.Value) 59 | |> List.ofSeq 60 | 61 | // [fsi:val it : string list = ["425"; "426"; "427"]] 62 | 63 | (** 64 | To ease the conversion of matched groups to primitives types, the assembly provides 65 | the FSharp.Text.RegexExtensions module. It contains extensions methods to convert matched groups 66 | to `int`, `uint32`, `int64`, `uint64`, `int16`, `uint16`, `byte`, `sbyte`, 67 | `float`, `single`, `decimal`, `DateTime`, `DateTimeOffset`, `TimeSpan`, `bool` and `char`: 68 | *) 69 | 70 | open FSharp.Text.RegexExtensions 71 | 72 | type TempRegex = Regex< @"^(?[\d\.]+)\s*°C$", noMethodPrefix = true > 73 | 74 | // the simplest extension gets an option string depending on Success 75 | TempRegex().Match("21.3°C").Temperature.TryValue 76 | // [fsi:val it : string option = Some "21.3"] 77 | 78 | // conversion to decimal in the happy case 79 | TempRegex().Match("21.3°C").Temperature.AsDecimal 80 | // [fsi:val it : decimal = 21.3M] 81 | 82 | // When not sure whether the match occured or the format is always correct use TryAs... 83 | // here it's successful 84 | TempRegex().Match("21.3°C").Temperature.TryAsDecimal 85 | // [fsi:val it : decimal option = Some 21.3M] 86 | 87 | // here it returns None because it's not °C, so it doesn't match 88 | TempRegex().Match("21.3°F").Temperature.TryAsDecimal 89 | // [fsi:val it : decimal option = None] 90 | 91 | // here it matches, but it is not a valid decimal 92 | TempRegex().Match("21.3.5°F").Temperature.TryAsDecimal 93 | // [fsi:val it : decimal option = None] 94 | 95 | type DateRegex = Regex< @"^Date:\s*(?\d{4}-\d{2}-\d{2})$", noMethodPrefix = true > 96 | 97 | // for dates, specify a format, especially for local or utc conversion 98 | DateRegex().Match("Date: 2019-06-18").Date.AsDateTime(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 99 | // [fsi:val it : System.DateTime = 18/06/2019 00:00:00] 100 | 101 | (** 102 | `TypedReplace` can be used with a match evaluator that takes a MatchType as an input. 103 | Here, the type of m is `NumberRegex.MatchType`, and has a Number property infered from the regular expression : 104 | *) 105 | 106 | type NumberRegex = Regex< @"(?\d+)" > 107 | 108 | let song = " 109 | 1, 2 buckle my shoe 110 | 3, 4 knock on the door 111 | 5, 6 pick up sticks 112 | 9, 10 a big fat hen." 113 | 114 | let numbers = 115 | Map.ofList 116 | [ 1, "one"; 2, "two"; 3, "three"; 4, "four"; 5, "five" 117 | 6, "six"; 7, "seven"; 8, "eight"; 9, "nine"; 10, "ten"] 118 | 119 | // using typed replace, you can use typed match in the provided function 120 | NumberRegex().TypedReplace(song, fun m -> numbers.[m.Number.AsInt] ) 121 | // [fsi:val it : string = ] 122 | // [fsi:"] 123 | // [fsi: one, two buckle my shoe] 124 | // [fsi: three, four knock on the door] 125 | // [fsi: five, six pick up sticks] 126 | // [fsi: nine, ten a big fat hen."] 127 | 128 | (** 129 | 130 | Contributing and copyright 131 | -------------------------- 132 | 133 | The project is hosted on [GitHub][gh] where you can [report issues][issues], fork 134 | the project and submit pull requests. If you're adding new public API, please also 135 | consider adding [samples][content] that can be turned into a documentation. You might 136 | also want to read [library design notes][readme] to understand how it works. 137 | 138 | The library is available under Public Domain license, which allows modification and 139 | redistribution for both commercial and non-commercial purposes. For more information see the 140 | [License file][license] in the GitHub repository. 141 | 142 | [content]: https://github.com/fsprojects/FSharp.Text.RegexProvider/tree/master/docs/content 143 | [gh]: https://github.com/fsprojects/FSharp.Text.RegexProvider 144 | [issues]: https://github.com/fsprojects/FSharp.Text.RegexProvider/issues 145 | [readme]: https://github.com/fsprojects/FSharp.Text.RegexProvider/blob/master/README.md 146 | [license]: https://github.com/fsprojects/FSharp.Text.RegexProvider/blob/master/LICENSE.txt 147 | *) 148 | -------------------------------------------------------------------------------- /docs/tools/generate.fsx: -------------------------------------------------------------------------------- 1 | //#load "../../.paket/load/netstandard2.0/docs/docs.group.fsx" 2 | #load "../../.paket/load/netstandard2.0/docs/FSharp.Compiler.Service.fsx" 3 | #load "../../.paket/load/netstandard2.0/docs/FSharp.Literate.fsx" 4 | #load "../../.paket/load/netstandard2.0/docs/Fable.React.fsx" 5 | #if !FAKE 6 | #r "netstandard" 7 | #endif 8 | 9 | open System 10 | open Fable.React 11 | open Fable.React.Props 12 | open FSharp.Literate 13 | 14 | let (>) x y = IO.Path.Combine(x,y) 15 | module Path = 16 | let root = __SOURCE_DIRECTORY__ > ".." 17 | let content = root > "content" 18 | let output = root > "output" 19 | let files = root > "files" 20 | 21 | let dir p = IO.Path.GetDirectoryName(p: string) 22 | let filename p = IO.Path.GetFileName(p: string) 23 | let changeExt ext p = IO.Path.ChangeExtension(p, ext) 24 | 25 | module Directory = 26 | let ensure dir = 27 | if not (IO.Directory.Exists dir) then 28 | IO.Directory.CreateDirectory dir |> ignore 29 | 30 | let copyRecursive (path: string) dest = 31 | let path = 32 | if not (path.EndsWith(string IO.Path.DirectorySeparatorChar)) then 33 | path + string IO.Path.DirectorySeparatorChar 34 | else 35 | path 36 | let trim (p: string) = 37 | if p.StartsWith(path) then 38 | p.Substring(path.Length) 39 | else 40 | failwithf "Cannot find path root" 41 | IO.Directory.EnumerateFiles(path, "*", IO.SearchOption.AllDirectories) 42 | |> Seq.iter (fun p -> 43 | let target = dest > trim p 44 | ensure(Path.dir target) 45 | IO.File.Copy(p, target, true)) 46 | 47 | 48 | 49 | 50 | type Template = 51 | { Name: string 52 | Description: string 53 | Body: string 54 | Author: string 55 | GitHub: string 56 | NuGet: string 57 | Root: string 58 | Tooltips: string } 59 | 60 | let properties = 61 | { Name = "FSharp.Text.RegexProvider" 62 | Description = "A type provider for regular expressions." 63 | Author = "Steffen Forkmann" 64 | GitHub = "https://github.com/fsprojects/FSharp.Text.RegexProvider" 65 | NuGet = "https://www.nuget.org/packages/FSharp.Text.RegexProvider" 66 | Body = "" 67 | Root = "." 68 | Tooltips = "" } 69 | 70 | let href t link = 71 | Href (t.Root + link) 72 | let src t link = 73 | Src (t.Root + link) 74 | 75 | let template t = 76 | fragment [] [ 77 | RawText "" 78 | RawText "\n" 79 | html [ Lang "en" ] 80 | [ head [ ] 81 | [ meta [ CharSet "utf-8" ] 82 | title [ ] [ str t.Name ] 83 | meta [ Name "viewport" 84 | HTMLAttr.Content "width=device-width, initial-scale=1.0" ] 85 | meta [ Name "description" 86 | HTMLAttr.Content t.Description ] 87 | meta [ Name "author" 88 | HTMLAttr.Content t.Author ] 89 | script [ Src "https://code.jquery.com/jquery-1.8.0.js" ] [ ] 90 | script [ Src "https://code.jquery.com/ui/1.8.23/jquery-ui.js" ] [ ] 91 | script [ Src "https://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js" ] [ ] 92 | link [ Href "https://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/css/bootstrap-combined.min.css" 93 | Rel "stylesheet" ] 94 | link [ Type "text/css" 95 | Rel "stylesheet" 96 | href t "/content/style.css" ] 97 | script [ Type "text/javascript" 98 | src t "/content/tips.js" ] 99 | [ ] ] 100 | body [ ] 101 | [ div [ Class "container" ] 102 | [ div [ Class "masthead" ] 103 | [ ul [ Class "nav nav-pills pull-right" ] 104 | [ li [ ] 105 | [ a [ Href "https://fsharp.org" ] 106 | [ str "fsharp.org" ] ] 107 | li [ ] 108 | [ a [ Href t.GitHub ] 109 | [ str "github page" ] ] ] 110 | h3 [ Class "muted" ] 111 | [ a [ href t "/index.html" ] 112 | [ str t.Name ] ] ] 113 | hr [ ] 114 | div [ Class "row" ] 115 | [ div [ Class "span9" 116 | Id "main" ] 117 | [ RawText t.Body ] 118 | div [ Class "span3" ] 119 | [ ul [ Class "nav nav-list" 120 | Id "menu" ] 121 | [ li [ Class "nav-header" ] 122 | [ str t.Name ] 123 | li [ ] 124 | [ a [ href t "/index.html" ] 125 | [ str "Home page" ] ] 126 | li [ Class "divider" ] 127 | [ ] 128 | li [ ] 129 | [ a [ Href t.NuGet ] 130 | [ str "Get Library via NuGet" ] ] 131 | li [ ] 132 | [ a [ Href t.GitHub ] 133 | [ str "Source Code on GitHub" ] ] 134 | li [ ] 135 | [ a [ href t "/license.html" ] 136 | [ str "License" ] ] 137 | li [ ] 138 | [ a [ href t "/release-notes.html" ] 139 | [ str "Release Notes" ] ] ] ] ] ] 140 | a [ Href t.GitHub ] 141 | [ img [ Style [ Position PositionOptions.Absolute 142 | Top "0" 143 | Right "0" 144 | Border "0" ] 145 | Src "https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" 146 | Alt "Fork me on GitHub" ] ] 147 | RawText t.Tooltips ] ] ] 148 | 149 | let write path html = 150 | use writer = System.IO.File.CreateText(path) 151 | Fable.ReactServer.Raw.writeTo writer (Fable.ReactServer.castHTMLNode html) 152 | 153 | let docPackagePath path = 154 | __SOURCE_DIRECTORY__ + @"/../../packages/docs/" + path 155 | let includeDir path = 156 | "-I:" + docPackagePath path 157 | let reference path = 158 | "-r:" + docPackagePath path 159 | let evaluationOptions = 160 | [| 161 | includeDir "FSharp.Core/lib/netstandard1.6/" 162 | includeDir "FSharp.Literate/lib/netstandard2.0/" 163 | includeDir "FSharp.Compiler.Service/lib/netstandard2.0/" 164 | reference "FSharp.Compiler.Service/lib/netstandard2.0/FSharp.Compiler.Service.dll" |] 165 | 166 | let compilerOptions = 167 | String.concat " " ( 168 | "-r:System.Runtime" 169 | :: Array.toList evaluationOptions) 170 | 171 | let parseFsx path = 172 | 173 | let doc = 174 | Literate.ParseScriptFile( 175 | path = path, 176 | compilerOptions = compilerOptions, 177 | fsiEvaluator = FSharp.Literate.FsiEvaluator(evaluationOptions)) 178 | 179 | let body = FSharp.Literate.Literate.FormatLiterateNodes(doc, OutputKind.Html, "", true, true) 180 | for err in doc.Errors do 181 | Printf.printfn "%A" err 182 | body, body.FormattedTips 183 | 184 | 185 | let parseMd path = 186 | let doc = 187 | Literate.ParseMarkdownFile( 188 | path, 189 | compilerOptions = compilerOptions, 190 | fsiEvaluator = FSharp.Literate.FsiEvaluator(evaluationOptions)) 191 | let body = FSharp.Literate.Literate.FormatLiterateNodes(doc, OutputKind.Html, "", true, true) 192 | for err in doc.Errors do 193 | Printf.printfn "%A" err 194 | body, body.FormattedTips 195 | 196 | let format (doc: LiterateDocument) = 197 | Formatting.format doc.MarkdownDocument true OutputKind.Html 198 | 199 | let processFile outdir path = 200 | let outfile = 201 | let name = path |> Path.filename |> Path.changeExt ".html" 202 | outdir > name 203 | 204 | let parse = 205 | match IO.Path.GetExtension(path) with 206 | | ".fsx" -> parseFsx 207 | | ".md" -> parseMd 208 | | ext -> failwithf "Unable to process doc for %s files" ext 209 | 210 | let body, tips = 211 | parse path 212 | let t = 213 | { properties with 214 | Body = format body 215 | Tooltips = tips } 216 | t 217 | |> template 218 | |> write outfile 219 | 220 | 221 | Directory.copyRecursive Path.files Path.output 222 | 223 | IO.Directory.EnumerateFiles Path.content 224 | |> Seq.iter (processFile Path.output) 225 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /tests/RegexProvider.Tests/RegexExtensions.Tests.fs: -------------------------------------------------------------------------------- 1 | module FSharp.Text.RegexProvider.Tests.RegexExtensionsTests 2 | 3 | open System 4 | open NUnit.Framework 5 | open FSharp.Text.RegexProvider 6 | open FSharp.Text.RegexExtensions 7 | open System.Globalization 8 | open FsUnit 9 | 10 | 11 | type PhoneRegex = Regex< @"^(\(\+(?\d+)\))?\s*(?[\d-]+$)", noMethodPrefix = true > 12 | [] 13 | let ``Group extension TryValue``() = 14 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryValue 15 | |> shouldEqual (Some "33") 16 | 17 | [] 18 | let ``Group extension TryValue when not available``() = 19 | PhoneRegex().Match("425-123-2345").Prefix.TryValue 20 | |> shouldEqual None 21 | 22 | module TestInt32 = 23 | [] 24 | let ``Group extension AsInt``() = 25 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsInt 26 | |> shouldEqual 33 27 | 28 | 29 | [] 30 | let ``Group extension TryAsInt when available``() = 31 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsInt 32 | |> shouldEqual (Some 33) 33 | 34 | [] 35 | let ``Group extension TryAsInt when not available``() = 36 | PhoneRegex().Match("425-123-2345").Prefix.TryAsInt 37 | |> shouldEqual None 38 | 39 | 40 | [] 41 | let ``Group extension TryAsInt when not valid``() = 42 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsInt 43 | |> shouldEqual None 44 | 45 | module TestUInt32 = 46 | [] 47 | let ``Group extension AsUInt32``() = 48 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsUInt32 49 | |> shouldEqual 33u 50 | 51 | 52 | [] 53 | let ``Group extension TryAsUInt32 when available``() = 54 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsUInt32 55 | |> shouldEqual (Some 33u) 56 | 57 | [] 58 | let ``Group extension TryAsUInt32 when not available``() = 59 | PhoneRegex().Match("425-123-2345").Prefix.TryAsUInt32 60 | |> shouldEqual None 61 | 62 | 63 | [] 64 | let ``Group extension TryAsUInt32 when not valid``() = 65 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsUInt32 66 | |> shouldEqual None 67 | 68 | 69 | module TestInt64 = 70 | [] 71 | let ``Group extension AsInt64``() = 72 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsInt64 73 | |> shouldEqual 33L 74 | 75 | 76 | [] 77 | let ``Group extension TryAsInt64 when available``() = 78 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsInt64 79 | |> shouldEqual (Some 33L) 80 | 81 | [] 82 | let ``Group extension TryAsInt64 when not available``() = 83 | PhoneRegex().Match("425-123-2345").Prefix.TryAsInt64 84 | |> shouldEqual None 85 | 86 | 87 | [] 88 | let ``Group extension TryAsInt64 when not valid``() = 89 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsInt64 90 | |> shouldEqual None 91 | 92 | module TestUInt64 = 93 | [] 94 | let ``Group extension AsUInt64``() = 95 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsUInt64 96 | |> shouldEqual 33UL 97 | 98 | 99 | [] 100 | let ``Group extension TryAsUInt64 when available``() = 101 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsUInt64 102 | |> shouldEqual (Some 33UL) 103 | 104 | [] 105 | let ``Group extension TryAsUInt64 when not available``() = 106 | PhoneRegex().Match("425-123-2345").Prefix.TryAsUInt64 107 | |> shouldEqual None 108 | 109 | 110 | [] 111 | let ``Group extension TryAsUInt64 when not valid``() = 112 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsUInt64 113 | |> shouldEqual None 114 | 115 | 116 | module TestInt16 = 117 | [] 118 | let ``Group extension AsInt16``() = 119 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsInt16 120 | |> shouldEqual 33s 121 | 122 | 123 | [] 124 | let ``Group extension TryAsInt16 when available``() = 125 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsInt16 126 | |> shouldEqual (Some 33s) 127 | 128 | [] 129 | let ``Group extension TryAsInt16 when not available``() = 130 | PhoneRegex().Match("425-123-2345").Prefix.TryAsInt16 131 | |> shouldEqual None 132 | 133 | 134 | [] 135 | let ``Group extension TryAsInt16 when not valid``() = 136 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsInt16 137 | |> shouldEqual None 138 | 139 | module TestUInt16 = 140 | [] 141 | let ``Group extension AsUInt16``() = 142 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsUInt16 143 | |> shouldEqual 33us 144 | 145 | 146 | [] 147 | let ``Group extension TryAsUInt16 when available``() = 148 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsUInt16 149 | |> shouldEqual (Some 33us) 150 | 151 | [] 152 | let ``Group extension TryAsUInt16 when not available``() = 153 | PhoneRegex().Match("425-123-2345").Prefix.TryAsUInt16 154 | |> shouldEqual None 155 | 156 | 157 | [] 158 | let ``Group extension TryAsUInt16 when not valid``() = 159 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsUInt16 160 | |> shouldEqual None 161 | 162 | 163 | module TestByte = 164 | [] 165 | let ``Group extension AsByte``() = 166 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsByte 167 | |> shouldEqual 33uy 168 | 169 | 170 | [] 171 | let ``Group extension TryAsByte when available``() = 172 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsByte 173 | |> shouldEqual (Some 33uy) 174 | 175 | [] 176 | let ``Group extension TryAsByte when not available``() = 177 | PhoneRegex().Match("425-123-2345").Prefix.TryAsByte 178 | |> shouldEqual None 179 | 180 | 181 | [] 182 | let ``Group extension TryAsByte when not valid``() = 183 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsByte 184 | |> shouldEqual None 185 | 186 | module TestSByte = 187 | [] 188 | let ``Group extension AsSByte``() = 189 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.AsSByte 190 | |> shouldEqual 33y 191 | 192 | 193 | [] 194 | let ``Group extension TryAsSByte when available``() = 195 | PhoneRegex().Match("(+33) 425-123-2345").Prefix.TryAsSByte 196 | |> shouldEqual (Some 33y) 197 | 198 | [] 199 | let ``Group extension TryAsSByte when not available``() = 200 | PhoneRegex().Match("425-123-2345").Prefix.TryAsSByte 201 | |> shouldEqual None 202 | 203 | 204 | [] 205 | let ``Group extension TryAsSByte when not valid``() = 206 | PhoneRegex().Match("425-123-2345").PhoneNumber.TryAsSByte 207 | |> shouldEqual None 208 | 209 | 210 | type TempRegex = Regex< @"^(?[\d\.*]+)\s*°C$", noMethodPrefix = true > 211 | module TestDecimal = 212 | [] 213 | let ``Group extension AsDecimal``() = 214 | TempRegex().Match("21.3°C").Temperature.AsDecimal 215 | |> shouldEqual 21.3m 216 | 217 | 218 | [] 219 | let ``Group extension TryAsDecimal when available``() = 220 | TempRegex().Match("21.3°C").Temperature.TryAsDecimal 221 | |> shouldEqual (Some 21.3m) 222 | 223 | [] 224 | let ``Group extension TryAsDecimal when not available``() = 225 | TempRegex().Match("°C").Temperature.TryAsDecimal 226 | |> shouldEqual None 227 | 228 | 229 | [] 230 | let ``Group extension TryAsDecimal when not valid``() = 231 | TempRegex().Match("21.3.5°C").Temperature.TryAsDecimal 232 | |> shouldEqual None 233 | 234 | module TestFloat = 235 | [] 236 | let ``Group extension AsFloat``() = 237 | TempRegex().Match("21.3°C").Temperature.AsFloat 238 | |> shouldEqual 21.3 239 | 240 | 241 | [] 242 | let ``Group extension TryAsFloat when available``() = 243 | TempRegex().Match("21.3°C").Temperature.TryAsFloat 244 | |> shouldEqual (Some 21.3) 245 | 246 | [] 247 | let ``Group extension TryAsFloat when not available``() = 248 | TempRegex().Match("°C").Temperature.TryAsFloat 249 | |> shouldEqual None 250 | 251 | 252 | [] 253 | let ``Group extension TryAsFloat when not valid``() = 254 | TempRegex().Match("21*3°C").Temperature.TryAsFloat 255 | |> shouldEqual None 256 | 257 | module TestSingle = 258 | [] 259 | let ``Group extension AsSingle``() = 260 | TempRegex().Match("21.3°C").Temperature.AsSingle 261 | |> shouldEqual 21.3f 262 | 263 | 264 | [] 265 | let ``Group extension TryAsSingle when available``() = 266 | TempRegex().Match("21.3°C").Temperature.TryAsSingle 267 | |> shouldEqual (Some 21.3f) 268 | 269 | [] 270 | let ``Group extension TryAsSingle when not available``() = 271 | TempRegex().Match("°C").Temperature.TryAsSingle 272 | |> shouldEqual None 273 | 274 | 275 | [] 276 | let ``Group extension TryAsSingle when not valid``() = 277 | TempRegex().Match("21*3°C").Temperature.TryAsSingle 278 | |> shouldEqual None 279 | 280 | type DateRegex = Regex< @"^Date:\s*(?\d{4}-\d{2}-\d{2})$", noMethodPrefix = true > 281 | module TestDateTime = 282 | [] 283 | let ``Group extension AsDateTime``() = 284 | DateRegex().Match("Date: 2019-06-18").Date.AsDateTime(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 285 | |> shouldEqual (DateTime(2019,6,18, 0,0,0,DateTimeKind.Utc)) 286 | 287 | 288 | [] 289 | let ``Group extension AsDateTime when available``() = 290 | DateRegex().Match("Date: 2019-06-18").Date.TryAsDateTime(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 291 | |> shouldEqual (Some (DateTime(2019,6,18, 0,0,0,DateTimeKind.Utc))) 292 | 293 | [] 294 | let ``Group extension AsDateTime when not available``() = 295 | DateRegex().Match("DateTime: 2019-06-18").Date.TryAsDateTime(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 296 | |> shouldEqual None 297 | 298 | 299 | [] 300 | let ``Group extension AsDateTime when not valid``() = 301 | DateRegex().Match("DateTime: 2019-99-18").Date.TryAsDateTime(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 302 | |> shouldEqual None 303 | 304 | module TestDateTimeOffset = 305 | [] 306 | let ``Group extension AsDateTimeOffset``() = 307 | DateRegex().Match("Date: 2019-06-18").Date.AsDateTimeOffset(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 308 | |> shouldEqual (DateTimeOffset(2019,6,18, 0,0,0,TimeSpan.Zero)) 309 | 310 | 311 | [] 312 | let ``Group extension TryAsDateTimeOffset when available``() = 313 | DateRegex().Match("Date: 2019-06-18").Date.TryAsDateTimeOffset(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 314 | |> shouldEqual (Some (DateTimeOffset(2019,6,18, 0,0,0,TimeSpan.Zero))) 315 | 316 | [] 317 | let ``Group extension TryAsDateTimeOffset when not available``() = 318 | DateRegex().Match("DateTime: 2019-06-18").Date.TryAsDateTimeOffset(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 319 | |> shouldEqual None 320 | 321 | 322 | [] 323 | let ``Group extension TryAsDateTimeOffset when not valid``() = 324 | DateRegex().Match("DateTime: 2019-99-18").Date.TryAsDateTimeOffset(DateTimeStyles.AssumeUniversal|||DateTimeStyles.AdjustToUniversal) 325 | |> shouldEqual None 326 | 327 | type TimeSpanRegex = Regex< @"^TimeSpan:\s*(?\d{2}:\d{2}:\d{2})$", noMethodPrefix = true > 328 | module TestTimeSpan = 329 | [] 330 | let ``Group extension AsTimeSpan``() = 331 | TimeSpanRegex().Match("TimeSpan: 13:39:24").TimeSpan.AsTimeSpan 332 | |> shouldEqual (TimeSpan(13,39,24)) 333 | 334 | 335 | [] 336 | let ``Group extension TryAsTimeSpan when available``() = 337 | TimeSpanRegex().Match("TimeSpan: 13:39:24").TimeSpan.TryAsTimeSpan 338 | |> shouldEqual (Some (TimeSpan(13,39,24))) 339 | 340 | [] 341 | let ``Group extension TryAsTimeSpan when not available``() = 342 | TimeSpanRegex().Match("Time: 13:39:24").TimeSpan.TryAsTimeSpan 343 | |> shouldEqual None 344 | 345 | 346 | [] 347 | let ``Group extension TryAsTimeSpan when not valid``() = 348 | TimeSpanRegex().Match("TimeSpan: 13:70:24").TimeSpan.TryAsTimeSpan 349 | |> shouldEqual None 350 | 351 | type BoolRegex = Regex< @"^Bool:\s*(?\w{4,5})$", noMethodPrefix = true > 352 | module TestBool = 353 | [] 354 | let ``Group extension AsBool``() = 355 | BoolRegex().Match("Bool: true").Bool.AsBool 356 | |> shouldEqual true 357 | 358 | 359 | [] 360 | let ``Group extension TryAsBool when available``() = 361 | BoolRegex().Match("Bool: false").Bool.TryAsBool 362 | |> shouldEqual (Some false) 363 | 364 | [] 365 | let ``Group extension TryAsBool when not available``() = 366 | BoolRegex().Match("Value: true").Bool.TryAsBool 367 | |> shouldEqual None 368 | 369 | 370 | [] 371 | let ``Group extension TryAsBool when not valid``() = 372 | BoolRegex().Match("Bool: right").Bool.TryAsBool 373 | |> shouldEqual None 374 | 375 | type CharRegex = Regex< @"^Char:\s*(?\w{1,2})$", noMethodPrefix = true > 376 | module TestChar = 377 | [] 378 | let ``Group extension AsChar``() = 379 | CharRegex().Match("Char: X").Char.AsChar 380 | |> shouldEqual 'X' 381 | 382 | 383 | [] 384 | let ``Group extension TryAsBool when available``() = 385 | CharRegex().Match("Char: X").Char.TryAsChar 386 | |> shouldEqual (Some 'X') 387 | 388 | [] 389 | let ``Group extension TryAsBool when not available``() = 390 | CharRegex().Match("Value: true").Char.TryAsChar 391 | |> shouldEqual None 392 | 393 | 394 | [] 395 | let ``Group extension TryAsBool when not valid``() = 396 | CharRegex().Match("Char: XY").Char.TryAsChar 397 | |> shouldEqual None 398 | -------------------------------------------------------------------------------- /src/RegexProvider/RegexProvider.fs: -------------------------------------------------------------------------------- 1 | namespace FSharp.Text.RegexProvider 2 | 3 | open ProviderImplementation.ProvidedTypes 4 | open FSharp.Text.RegexProvider.Helper 5 | open System 6 | open System.IO 7 | open System.Text.RegularExpressions 8 | open Microsoft.FSharp.Core.CompilerServices 9 | 10 | module internal TypedRegex = 11 | let typedRegex() = 12 | let regexType = erasedType thisAssembly rootNamespace "Regex" false 13 | regexType.DefineStaticParameters( 14 | parameters = 15 | [ 16 | ProvidedStaticParameter("pattern", typeof) 17 | ProvidedStaticParameter("noMethodPrefix", typeof, false) 18 | ], 19 | instantiationFunction = (fun typeName parameterValues -> 20 | match parameterValues with 21 | | [| :? string as pattern; :? bool as noMethodPrefix |] -> 22 | let typeSet = createTypeSet() 23 | 24 | let getMethodName baseName = 25 | if noMethodPrefix then baseName 26 | else sprintf "Typed%s" baseName 27 | 28 | let matchType = runtimeType"MatchType" true typeSet 29 | 30 | for group in Regex(pattern).GetGroupNames() do 31 | let property = 32 | ProvidedProperty( 33 | propertyName = (if group <> "0" then group else "CompleteMatch"), 34 | propertyType = typeof, 35 | getterCode = (fun args -> <@@ (%%args.[0]:Match).Groups.[group] @@>)) 36 | property.AddXmlDoc(sprintf @"Gets the ""%s"" group from this match" group) 37 | matchType.AddMember property 38 | 39 | let matchMethod = 40 | ProvidedMethod( 41 | methodName = getMethodName "NextMatch", 42 | parameters = [], 43 | returnType = matchType, 44 | invokeCode = (fun args -> <@@ (%%args.[0]:Match).NextMatch() @@>)) 45 | matchMethod.AddXmlDoc "Searches the specified input string for the next occurrence of this regular expression." 46 | 47 | matchType.AddMember matchMethod 48 | 49 | 50 | let regexType = erasedType thisAssembly rootNamespace typeName true 51 | regexType.AddXmlDoc "A strongly typed interface to the regular expression '%s'" 52 | 53 | regexType.AddMember matchType 54 | 55 | let isMatchMethod = 56 | ProvidedMethod( 57 | methodName = getMethodName "IsMatch", 58 | parameters = [ProvidedParameter("input", typeof)], 59 | returnType = typeof, 60 | invokeCode = (fun args -> <@@ Regex.IsMatch(%%args.[0], pattern) @@>), 61 | isStatic = true) 62 | isMatchMethod.AddXmlDoc "Indicates whether the regular expression finds a match in the specified input string" 63 | 64 | regexType.AddMember isMatchMethod 65 | 66 | let matchMethod = 67 | ProvidedMethod( 68 | methodName = getMethodName "Match", 69 | parameters = [ProvidedParameter("input", typeof)], 70 | returnType = matchType, 71 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Match(%%args.[1]) @@>)) 72 | matchMethod.AddXmlDoc "Searches the specified input string for the first occurrence of this regular expression" 73 | 74 | regexType.AddMember matchMethod 75 | 76 | let matchStartAtMethod = 77 | ProvidedMethod( 78 | methodName = getMethodName "Match", 79 | parameters = [ProvidedParameter("input", typeof) 80 | ProvidedParameter("startat", typeof)], 81 | returnType = matchType, 82 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Match(%%args.[1], %%args.[2]) @@>)) 83 | matchStartAtMethod.AddXmlDoc "Searches the specified input string for the first occurrence of this regular expression, beginning at the specified starting position." 84 | 85 | regexType.AddMember matchStartAtMethod 86 | 87 | let matchBeginningLengthMethod = 88 | ProvidedMethod( 89 | methodName = getMethodName "Match", 90 | parameters = [ProvidedParameter("input", typeof) 91 | ProvidedParameter("beginning", typeof) 92 | ProvidedParameter("length",typeof)], 93 | returnType = matchType, 94 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Match(%%args.[1], %%args.[2], %%args.[3] ) @@>)) 95 | matchBeginningLengthMethod.AddXmlDoc "Searches the specified input string for the first occurrence of this regular expression, beginning at the specified starting position and searching only the specified number of characters." 96 | 97 | regexType.AddMember matchBeginningLengthMethod 98 | 99 | let tryMatchMethod = 100 | ProvidedMethod( 101 | methodName = "Try" + getMethodName "Match", 102 | parameters = [ProvidedParameter("input", typeof)], 103 | returnType = optionType matchType, 104 | invokeCode = (fun args -> 105 | <@@ let m = (%%args.[0]:Regex).Match(%%args.[1]) 106 | if m.Success then 107 | Some m 108 | else 109 | None @@>)) 110 | tryMatchMethod.AddXmlDoc "Searches the specified input string for the first occurrence of this regular expression." 111 | 112 | regexType.AddMember tryMatchMethod 113 | 114 | let tryMatchStartAtMethod = 115 | ProvidedMethod( 116 | methodName = "Try" + getMethodName "Match", 117 | parameters = [ProvidedParameter("input", typeof) 118 | ProvidedParameter("startat", typeof)], 119 | returnType = optionType matchType, 120 | invokeCode = (fun args -> 121 | <@@ let m = (%%args.[0]:Regex).Match(%%args.[1], %%args.[2]) 122 | if m.Success then 123 | Some m 124 | else 125 | None @@>)) 126 | tryMatchStartAtMethod.AddXmlDoc "Searches the specified input string for the first occurrence of this regular expression, beginning at the specified starting position." 127 | 128 | regexType.AddMember tryMatchStartAtMethod 129 | 130 | let tryMatchBeginningLengthMethod = 131 | ProvidedMethod( 132 | methodName = "Try" + getMethodName "Match", 133 | parameters = [ProvidedParameter("input", typeof) 134 | ProvidedParameter("beginning", typeof) 135 | ProvidedParameter("length", typeof)], 136 | returnType = optionType matchType, 137 | invokeCode = (fun args -> 138 | <@@ let m = (%%args.[0]:Regex).Match(%%args.[1], %%args.[2], %%args.[3]) 139 | if m.Success then 140 | Some m 141 | else 142 | None @@>)) 143 | tryMatchBeginningLengthMethod.AddXmlDoc "Searches the specified input string for the first occurrence of this regular expression, beginning at the specified starting position and searching only the specified number of characters." 144 | 145 | regexType.AddMember tryMatchBeginningLengthMethod 146 | 147 | let matchesMethod = 148 | ProvidedMethod( 149 | methodName = getMethodName "Matches", 150 | parameters = [ProvidedParameter("input", typeof)], 151 | returnType = seqType matchType, 152 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Matches(%%args.[1]) |> Seq.cast @@>)) 153 | matchesMethod.AddXmlDoc "Searches the specified input string for all occurrences of this regular expression." 154 | 155 | regexType.AddMember matchesMethod 156 | 157 | let matchesStartAtMethod = 158 | ProvidedMethod( 159 | methodName = getMethodName "Matches", 160 | parameters = [ProvidedParameter("input", typeof) 161 | ProvidedParameter("startat", typeof)], 162 | returnType = seqType matchType, 163 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Matches(%%args.[1], %%args.[2]) |> Seq.cast @@>)) 164 | matchesStartAtMethod.AddXmlDoc "Searches the specified input string for all occurrences of this regular expression, beginning at the specified starting position in the string." 165 | 166 | regexType.AddMember matchesStartAtMethod 167 | 168 | let replaceMethod = 169 | ProvidedMethod( 170 | methodName = getMethodName "Replace", 171 | parameters = [ProvidedParameter("input", typeof) 172 | ProvidedParameter("evaluator", funType matchType typeof)], 173 | returnType = typeof, 174 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Replace(%%args.[1], MatchEvaluator(%%args.[2] )) @@>)) 175 | replaceMethod.AddXmlDoc "In a specified input string, replaces all strings that match a specified regular expression with a string returned by an evaluator function." 176 | 177 | regexType.AddMember replaceMethod 178 | 179 | let replaceCountMethod = 180 | ProvidedMethod( 181 | methodName = getMethodName "Replace", 182 | parameters = [ProvidedParameter("input", typeof) 183 | ProvidedParameter("evaluator", funType matchType typeof) 184 | ProvidedParameter("count", typeof)], 185 | returnType = typeof, 186 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Replace(%%args.[1], MatchEvaluator(%%args.[2] ), %%args.[3]) @@>)) 187 | replaceCountMethod.AddXmlDoc "In a specified input string, replaces a specified maximum number of strings that match a specified regular expression with a string returned by an evaluator function." 188 | 189 | regexType.AddMember replaceCountMethod 190 | 191 | let replaceCountStartAtMethod = 192 | ProvidedMethod( 193 | methodName = getMethodName "Replace", 194 | parameters = [ProvidedParameter("input", typeof) 195 | ProvidedParameter("evaluator", funType matchType typeof) 196 | ProvidedParameter("count", typeof) 197 | ProvidedParameter("startat", typeof)], 198 | returnType = typeof, 199 | invokeCode = (fun args -> <@@ (%%args.[0]:Regex).Replace(%%args.[1], MatchEvaluator(%%args.[2] ),%%args.[3], %%args.[4]) @@>)) 200 | replaceCountStartAtMethod.AddXmlDoc "In a specified input substring, replaces a specified maximum number of strings that match a specified regular expression with a string returned by an evaluator function." 201 | 202 | regexType.AddMember replaceCountStartAtMethod 203 | 204 | let ctor = 205 | ProvidedConstructor( 206 | parameters = [], 207 | invokeCode = (fun args -> <@@ Regex(pattern) @@>)) 208 | 209 | ctor.AddXmlDoc "Initializes a regular expression instance" 210 | regexType.AddMember ctor 211 | 212 | let ctor = 213 | ProvidedConstructor( 214 | parameters = [ProvidedParameter("options", typeof)], 215 | invokeCode = (fun args -> <@@ Regex(pattern, %%args.[0]) @@>)) 216 | ctor.AddXmlDoc "Initializes a regular expression instance, with options that modify the pattern." 217 | regexType.AddMember ctor 218 | 219 | let ctor = 220 | ProvidedConstructor( 221 | parameters = [ProvidedParameter("options", typeof) 222 | ProvidedParameter("matchTimeout", typeof)], 223 | invokeCode = (fun args -> <@@ Regex(pattern, %%args.[0], %%args.[1]) @@>)) 224 | ctor.AddXmlDoc "Initializes a regular expression instance, with options that modify the pattern and a value that specifies how long a pattern matching method should attempt a match before it times out." 225 | regexType.AddMember ctor 226 | 227 | regexType 228 | | _ -> failwith "unexpected parameter values")) 229 | regexType 230 | 231 | [] 232 | type public RegexProvider(cfg:TypeProviderConfig) = 233 | inherit TypeProviderForNamespaces(cfg, rootNamespace, [TypedRegex.typedRegex()]) 234 | 235 | 236 | [] 237 | do () 238 | -------------------------------------------------------------------------------- /.paket/Paket.Restore.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 8 | 9 | true 10 | $(MSBuildThisFileDirectory) 11 | $(MSBuildThisFileDirectory)..\ 12 | $(PaketRootPath)paket-files\paket.restore.cached 13 | $(PaketRootPath)paket.lock 14 | classic 15 | proj 16 | assembly 17 | native 18 | /Library/Frameworks/Mono.framework/Commands/mono 19 | mono 20 | 21 | 22 | $(PaketRootPath)paket.bootstrapper.exe 23 | $(PaketToolsPath)paket.bootstrapper.exe 24 | $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\ 25 | 26 | 27 | 28 | 29 | $(PaketRootPath)paket.exe 30 | $(PaketToolsPath)paket.exe 31 | $(PaketToolsPath)paket.exe 32 | $(_PaketBootStrapperExeDir)paket.exe 33 | paket.exe 34 | 35 | 36 | $(PaketRootPath)paket 37 | $(PaketToolsPath)paket 38 | $(PaketToolsPath)paket 39 | 40 | 41 | $(PaketRootPath)paket.exe 42 | $(PaketToolsPath)paket.exe 43 | 44 | 45 | $(PaketBootStrapperExeDir)paket.exe 46 | 47 | 48 | paket 49 | 50 | 51 | <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)")) 52 | dotnet "$(PaketExePath)" 53 | $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" 54 | "$(PaketExePath)" 55 | 56 | 57 | "$(PaketBootStrapperExePath)" 58 | $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" 59 | 60 | 61 | 62 | 63 | true 64 | true 65 | 66 | 67 | True 68 | 69 | $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/')) 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | true 81 | $(NoWarn);NU1603;NU1604;NU1605;NU1608 82 | 83 | 84 | 85 | 86 | /usr/bin/shasum "$(PaketRestoreCacheFile)" | /usr/bin/awk '{ print $1 }' 87 | /usr/bin/shasum "$(PaketLockFilePath)" | /usr/bin/awk '{ print $1 }' 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)')) 104 | $([System.IO.File]::ReadAllText('$(PaketLockFilePath)')) 105 | true 106 | false 107 | true 108 | 109 | 110 | 114 | 115 | true 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached 132 | 133 | $(MSBuildProjectFullPath).paket.references 134 | 135 | $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references 136 | 137 | $(MSBuildProjectDirectory)\paket.references 138 | 139 | false 140 | true 141 | true 142 | references-file-or-cache-not-found 143 | 144 | 145 | 146 | 147 | $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)')) 148 | $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)')) 149 | references-file 150 | false 151 | 152 | 153 | 154 | 155 | false 156 | 157 | 158 | 159 | 160 | true 161 | target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths) 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | false 172 | true 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length) 184 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) 185 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) 186 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4]) 187 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5]) 188 | 189 | 190 | %(PaketReferencesFileLinesInfo.PackageVersion) 191 | All 192 | runtime 193 | runtime 194 | true 195 | true 196 | 197 | 198 | 199 | 200 | $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0]) 210 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1]) 211 | 212 | 213 | %(PaketCliToolFileLinesInfo.PackageVersion) 214 | 215 | 216 | 217 | 221 | 222 | 223 | 224 | 225 | 226 | false 227 | $(MSBuildVersion) 228 | 15.8.0 229 | 230 | 231 | 232 | 233 | 234 | <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/> 235 | 236 | 237 | 238 | 239 | 240 | $(MSBuildProjectDirectory)/$(MSBuildProjectFile) 241 | true 242 | false 243 | true 244 | false 245 | true 246 | false 247 | true 248 | false 249 | true 250 | $(PaketIntermediateOutputPath)\$(Configuration) 251 | $(PaketIntermediateOutputPath) 252 | 253 | 254 | 255 | <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion).nuspec"/> 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 311 | 312 | 355 | 356 | 398 | 399 | 440 | 441 | 442 | 443 | -------------------------------------------------------------------------------- /src/RegexProvider/ProvidedTypes.fsi: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation 2005-2014 and other contributors. 2 | // This sample code is provided "as is" without warranty of any kind. 3 | // We disclaim all warranties, either express or implied, including the 4 | // warranties of merchantability and fitness for a particular purpose. 5 | // 6 | // This file contains a set of helper types and methods for providing types in an implementation 7 | // of ITypeProvider. 8 | // 9 | // This code has been modified and is appropriate for use in conjunction with the F# 3.0-4.0 releases 10 | 11 | 12 | namespace ProviderImplementation.ProvidedTypes 13 | 14 | open System 15 | open System.Collections.Generic 16 | open System.Reflection 17 | open System.Linq.Expressions 18 | open Microsoft.FSharp.Quotations 19 | open Microsoft.FSharp.Core.CompilerServices 20 | 21 | /// Represents an erased provided parameter 22 | [] 23 | type ProvidedParameter = 24 | inherit ParameterInfo 25 | 26 | /// Create a new provided parameter. 27 | new : parameterName: string * parameterType: Type * ?isOut: bool * ?optionalValue: obj -> ProvidedParameter 28 | 29 | /// Indicates if the parameter is marked as ParamArray 30 | member IsParamArray: bool with set 31 | 32 | /// Indicates if the parameter is marked as ReflectedDefinition 33 | member IsReflectedDefinition: bool with set 34 | 35 | /// Indicates if the parameter has a default value 36 | member HasDefaultParameterValue: bool 37 | 38 | /// Add a custom attribute to the provided parameter. 39 | member AddCustomAttribute: CustomAttributeData -> unit 40 | 41 | /// Represents a provided static parameter. 42 | [] 43 | type ProvidedStaticParameter = 44 | inherit ParameterInfo 45 | 46 | /// Create a new provided static parameter, for use with DefineStaticParamaeters on a provided type definition. 47 | new: parameterName: string * parameterType: Type * ?parameterDefaultValue: obj -> ProvidedStaticParameter 48 | 49 | /// Add XML documentation information to this provided constructor 50 | member AddXmlDoc: xmlDoc: string -> unit 51 | 52 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 53 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 54 | 55 | 56 | /// Represents an erased provided constructor. 57 | [] 58 | type ProvidedConstructor = 59 | inherit ConstructorInfo 60 | 61 | /// When making a cross-targeting type provider, use this method instead of the ProvidedConstructor constructor from ProvidedTypes 62 | new: parameters: ProvidedParameter list * invokeCode: (Expr list -> Expr) -> ProvidedConstructor 63 | 64 | /// Add a 'Obsolete' attribute to this provided constructor 65 | member AddObsoleteAttribute: message: string * ?isError: bool -> unit 66 | 67 | /// Add XML documentation information to this provided constructor 68 | member AddXmlDoc: xmlDoc: string -> unit 69 | 70 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 71 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 72 | 73 | /// Add XML documentation information to this provided constructor, where the documentation is re-computed every time it is required. 74 | member AddXmlDocComputed: xmlDocFunction: (unit -> string) -> unit 75 | 76 | /// Set the target and arguments of the base constructor call. Only used for generated types. 77 | member BaseConstructorCall: (Expr list -> ConstructorInfo * Expr list) with set 78 | 79 | /// Set a flag indicating that the constructor acts like an F# implicit constructor, so the 80 | /// parameters of the constructor become fields and can be accessed using Expr.GlobalVar with the 81 | /// same name. 82 | member IsImplicitConstructor: bool with get,set 83 | 84 | /// Add definition location information to the provided constructor. 85 | member AddDefinitionLocation: line:int * column:int * filePath:string -> unit 86 | 87 | member IsTypeInitializer: bool with get,set 88 | 89 | /// This method is for internal use only in the type provider SDK 90 | member internal GetInvokeCode: Expr list -> Expr 91 | 92 | 93 | 94 | [] 95 | type ProvidedMethod = 96 | inherit MethodInfo 97 | 98 | /// When making a cross-targeting type provider, use this method instead of the ProvidedMethod constructor from ProvidedTypes 99 | new: methodName: string * parameters: ProvidedParameter list * returnType: Type * ?invokeCode: (Expr list -> Expr) * ?isStatic: bool -> ProvidedMethod 100 | 101 | /// Add XML documentation information to this provided method 102 | member AddObsoleteAttribute: message: string * ?isError: bool -> unit 103 | 104 | /// Add XML documentation information to this provided constructor 105 | member AddXmlDoc: xmlDoc: string -> unit 106 | 107 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 108 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 109 | 110 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 111 | /// The documentation is re-computed every time it is required. 112 | member AddXmlDocComputed: xmlDocFunction: (unit -> string) -> unit 113 | 114 | member AddMethodAttrs: attributes:MethodAttributes -> unit 115 | 116 | /// Set the method attributes of the method. By default these are simple 'MethodAttributes.Public' 117 | member SetMethodAttrs: attributes:MethodAttributes -> unit 118 | 119 | /// Add definition location information to the provided type definition. 120 | member AddDefinitionLocation: line:int * column:int * filePath:string -> unit 121 | 122 | /// Add a custom attribute to the provided method definition. 123 | member AddCustomAttribute: CustomAttributeData -> unit 124 | 125 | /// Define the static parameters available on a statically parameterized method 126 | member DefineStaticParameters: parameters: ProvidedStaticParameter list * instantiationFunction: (string -> obj[] -> ProvidedMethod) -> unit 127 | 128 | /// This method is for internal use only in the type provider SDK 129 | member internal GetInvokeCode: (Expr list -> Expr) option 130 | 131 | 132 | /// Represents an erased provided property. 133 | [] 134 | type ProvidedProperty = 135 | inherit PropertyInfo 136 | 137 | /// Create a new provided property. It is not initially associated with any specific provided type definition. 138 | new: propertyName: string * propertyType: Type * ?getterCode: (Expr list -> Expr) * ?setterCode: (Expr list -> Expr) * ?isStatic: bool * ?indexParameters: ProvidedParameter list -> ProvidedProperty 139 | 140 | /// Add a 'Obsolete' attribute to this provided property 141 | member AddObsoleteAttribute: message: string * ?isError: bool -> unit 142 | 143 | /// Add XML documentation information to this provided constructor 144 | member AddXmlDoc: xmlDoc: string -> unit 145 | 146 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 147 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 148 | 149 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 150 | /// The documentation is re-computed every time it is required. 151 | member AddXmlDocComputed: xmlDocFunction: (unit -> string) -> unit 152 | 153 | /// Get or set a flag indicating if the property is static. 154 | member IsStatic: bool 155 | 156 | /// Add definition location information to the provided type definition. 157 | member AddDefinitionLocation: line:int * column:int * filePath:string -> unit 158 | 159 | /// Add a custom attribute to the provided property definition. 160 | member AddCustomAttribute: CustomAttributeData -> unit 161 | 162 | 163 | /// Represents an erased provided property. 164 | [] 165 | type ProvidedEvent = 166 | inherit EventInfo 167 | 168 | /// Create a new provided event. It is not initially associated with any specific provided type definition. 169 | new: eventName: string * eventHandlerType: Type * adderCode: (Expr list -> Expr) * removerCode: (Expr list -> Expr) * ?isStatic: bool -> ProvidedEvent 170 | 171 | /// Add XML documentation information to this provided constructor 172 | member AddXmlDoc: xmlDoc: string -> unit 173 | 174 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 175 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 176 | 177 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 178 | /// The documentation is re-computed every time it is required. 179 | member AddXmlDocComputed: xmlDocFunction: (unit -> string) -> unit 180 | 181 | /// Get a flag indicating if the property is static. 182 | member IsStatic: bool with get 183 | 184 | /// Add definition location information to the provided type definition. 185 | member AddDefinitionLocation: line:int * column:int * filePath:string -> unit 186 | 187 | 188 | /// Represents an erased provided field. 189 | [] 190 | type ProvidedField = 191 | inherit FieldInfo 192 | 193 | /// Create a new provided field. It is not initially associated with any specific provided type definition. 194 | new: fieldName: string * fieldType: Type -> ProvidedField 195 | 196 | /// Add a 'Obsolete' attribute to this provided field 197 | member AddObsoleteAttribute: message: string * ?isError: bool -> unit 198 | 199 | /// Add XML documentation information to this provided field 200 | member AddXmlDoc: xmlDoc: string -> unit 201 | 202 | /// Add XML documentation information to this provided field, where the computation of the documentation is delayed until necessary 203 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 204 | 205 | /// Add XML documentation information to this provided field, where the computation of the documentation is delayed until necessary 206 | /// The documentation is re-computed every time it is required. 207 | member AddXmlDocComputed: xmlDocFunction: (unit -> string) -> unit 208 | 209 | /// Add definition location information to the provided field definition. 210 | member AddDefinitionLocation: line:int * column:int * filePath:string -> unit 211 | 212 | member SetFieldAttributes: attributes: FieldAttributes -> unit 213 | 214 | /// Create a new provided literal field. It is not initially associated with any specific provided type definition. 215 | static member Literal : fieldName: string * fieldType: Type * literalValue:obj -> ProvidedField 216 | 217 | 218 | /// Represents an array or other symbolic type involving a provided type as the argument. 219 | /// See the type provider spec for the methods that must be implemented. 220 | /// Note that the type provider specification does not require us to implement pointer-equality for provided types. 221 | [] 222 | type ProvidedTypeSymbol = 223 | inherit TypeDelegator 224 | 225 | /// For example, kg 226 | member IsFSharpTypeAbbreviation: bool 227 | 228 | /// For example, int or int 229 | member IsFSharpUnitAnnotated: bool 230 | 231 | /// Helpers to build symbolic provided types 232 | [] 233 | type ProvidedTypeBuilder = 234 | 235 | /// Like typ.MakeGenericType, but will also work with unit-annotated types 236 | static member MakeGenericType: genericTypeDefinition: Type * genericArguments: Type list -> Type 237 | 238 | /// Like methodInfo.MakeGenericMethod, but will also work with unit-annotated types and provided types 239 | static member MakeGenericMethod: genericMethodDefinition: MethodInfo * genericArguments: Type list -> MethodInfo 240 | 241 | /// Like FsharpType.MakeTupleType, but will also work with unit-annotated types and provided types 242 | static member MakeTupleType: args: Type list -> Type 243 | 244 | 245 | /// Helps create erased provided unit-of-measure annotations. 246 | [] 247 | type ProvidedMeasureBuilder = 248 | 249 | /// Gets the measure indicating the "1" unit of measure, that is the unitless measure. 250 | static member One: Type 251 | 252 | /// Returns the measure indicating the product of two units of measure, e.g. kg * m 253 | static member Product: measure1: Type * measure2: Type -> Type 254 | 255 | /// Returns the measure indicating the inverse of two units of measure, e.g. 1 / s 256 | static member Inverse: denominator: Type -> Type 257 | 258 | /// Returns the measure indicating the ratio of two units of measure, e.g. kg / m 259 | static member Ratio: numerator: Type * denominator: Type -> Type 260 | 261 | /// Returns the measure indicating the square of a unit of measure, e.g. m * m 262 | static member Square: ``measure``: Type -> Type 263 | 264 | /// Returns the measure for an SI unit from the F# core library, where the string is in capitals and US spelling, e.g. Meter 265 | static member SI: unitName:string -> Type 266 | 267 | /// Returns a type where the type has been annotated with the given types and/or units-of-measure. 268 | /// e.g. float, Vector 269 | static member AnnotateType: basic: Type * argument: Type list -> Type 270 | 271 | 272 | /// Represents a provided type definition. 273 | [] 274 | type ProvidedTypeDefinition = 275 | inherit TypeDelegator 276 | 277 | /// When making a cross-targeting type provider, use this method instead of the corresponding ProvidedTypeDefinition constructor from ProvidedTypes 278 | new: className: string * baseType: Type option * ?hideObjectMethods: bool * ?nonNullable: bool * ?isErased: bool * ?isSealed: bool * ?isInterface: bool -> ProvidedTypeDefinition 279 | 280 | /// When making a cross-targeting type provider, use this method instead of the corresponding ProvidedTypeDefinition constructor from ProvidedTypes 281 | new: assembly: Assembly * namespaceName: string * className: string * baseType: Type option * ?hideObjectMethods: bool * ?nonNullable: bool * ?isErased: bool * ?isSealed: bool * ?isInterface: bool -> ProvidedTypeDefinition 282 | 283 | /// Add the given type as an implemented interface. 284 | member AddInterfaceImplementation: interfaceType: Type -> unit 285 | 286 | /// Add the given function as a set of on-demand computed interfaces. 287 | member AddInterfaceImplementationsDelayed: interfacesFunction:(unit -> Type list)-> unit 288 | 289 | /// Specifies that the given method body implements the given method declaration. 290 | member DefineMethodOverride: methodInfoBody: ProvidedMethod * methodInfoDeclaration: MethodInfo -> unit 291 | 292 | /// Specifies that the given method bodies implement the given method declarations 293 | member DefineMethodOverridesDelayed: (unit -> (ProvidedMethod * MethodInfo) list) -> unit 294 | 295 | /// Add a 'Obsolete' attribute to this provided type definition 296 | member AddObsoleteAttribute: message: string * ?isError: bool -> unit 297 | 298 | /// Add XML documentation information to this provided constructor 299 | member AddXmlDoc: xmlDoc: string -> unit 300 | 301 | /// Set the base type 302 | member SetBaseType: Type -> unit 303 | 304 | /// Set the base type to a lazily evaluated value. Use this to delay realization of the base type as late as possible. 305 | member SetBaseTypeDelayed: baseTypeFunction:(unit -> Type) -> unit 306 | 307 | /// Set underlying type for generated enums 308 | member SetEnumUnderlyingType: Type -> unit 309 | 310 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary. 311 | /// The documentation is only computed once. 312 | member AddXmlDocDelayed: xmlDocFunction: (unit -> string) -> unit 313 | 314 | /// Add XML documentation information to this provided constructor, where the computation of the documentation is delayed until necessary 315 | /// The documentation is re-computed every time it is required. 316 | member AddXmlDocComputed: xmlDocFunction: (unit -> string) -> unit 317 | 318 | /// Set the attributes on the provided type. This fully replaces the default TypeAttributes. 319 | member SetAttributes: TypeAttributes -> unit 320 | 321 | /// Add a method, property, nested type or other member to a ProvidedTypeDefinition 322 | member AddMember: memberInfo:MemberInfo -> unit 323 | 324 | /// Add a set of members to a ProvidedTypeDefinition 325 | member AddMembers: memberInfos:list<#MemberInfo> -> unit 326 | 327 | /// Add a member to a ProvidedTypeDefinition, delaying computation of the members until required by the compilation context. 328 | member AddMemberDelayed: memberFunction:(unit -> #MemberInfo) -> unit 329 | 330 | /// Add a set of members to a ProvidedTypeDefinition, delaying computation of the members until required by the compilation context. 331 | member AddMembersDelayed: membersFunction:(unit -> list<#MemberInfo>) -> unit 332 | 333 | /// Add the types of the generated assembly as generative types, where types in namespaces get hierarchically positioned as nested types. 334 | member AddAssemblyTypesAsNestedTypesDelayed: assemblyFunction:(unit -> Assembly) -> unit 335 | 336 | /// Define the static parameters available on a statically parameterized type 337 | member DefineStaticParameters: parameters: ProvidedStaticParameter list * instantiationFunction: (string -> obj[] -> ProvidedTypeDefinition) -> unit 338 | 339 | /// Add definition location information to the provided type definition. 340 | member AddDefinitionLocation: line:int * column:int * filePath:string -> unit 341 | 342 | /// Suppress Object entries in intellisense menus in instances of this provided type 343 | member HideObjectMethods: bool 344 | 345 | /// Disallows the use of the null literal. 346 | member NonNullable: bool 347 | 348 | /// Get a flag indicating if the ProvidedTypeDefinition is erased 349 | member IsErased: bool 350 | 351 | /// Get or set a flag indicating if the ProvidedTypeDefinition has type-relocation suppressed 352 | [] 353 | member SuppressRelocation: bool with get,set 354 | 355 | // This method is used by Debug.fs 356 | member ApplyStaticArguments: name:string * args:obj[] -> ProvidedTypeDefinition 357 | 358 | /// Add a custom attribute to the provided type definition. 359 | member AddCustomAttribute: CustomAttributeData -> unit 360 | 361 | /// Emulate the F# type provider type erasure mechanism to get the 362 | /// actual (erased) type. We erase ProvidedTypes to their base type 363 | /// and we erase array of provided type to array of base type. In the 364 | /// case of generics all the generic type arguments are also recursively 365 | /// replaced with the erased-to types 366 | static member EraseType: typ:Type -> Type 367 | 368 | /// Get or set a utility function to log the creation of root Provided Type. Used to debug caching/invalidation. 369 | static member Logger: (string -> unit) option ref 370 | 371 | 372 | #if !NO_GENERATIVE 373 | /// A provided generated assembly 374 | type ProvidedAssembly = 375 | 376 | inherit Assembly 377 | 378 | /// Create a provided generated assembly 379 | new: assemblyName: AssemblyName * assemblyFileName:string -> ProvidedAssembly 380 | 381 | /// Create a provided generated assembly using a temporary file as the interim assembly storage 382 | new: unit -> ProvidedAssembly 383 | 384 | /// Emit the given provided type definitions as part of the assembly 385 | /// and adjust the 'Assembly' property of all provided type definitions to return that 386 | /// assembly. 387 | /// 388 | /// The assembly is only emitted when the Assembly property on the root type is accessed for the first time. 389 | /// The host F# compiler does this when processing a generative type declaration for the type. 390 | member AddTypes: types: ProvidedTypeDefinition list -> unit 391 | 392 | /// 393 | /// Emit the given nested provided type definitions as part of the assembly. 394 | /// and adjust the 'Assembly' property of all provided type definitions to return that 395 | /// assembly. 396 | /// 397 | /// A path of type names to wrap the generated types. The generated types are then generated as nested types. 398 | member AddNestedTypes: types: ProvidedTypeDefinition list * enclosingGeneratedTypeNames: string list -> unit 399 | 400 | #endif 401 | 402 | 403 | 404 | [] 405 | /// Represents the context for which code is to be generated. Normally you should not need to use this directly. 406 | type ProvidedTypesContext = 407 | 408 | /// Try to find the given target assembly in the context 409 | member TryBindAssemblyNameToTarget: aref: AssemblyName -> Choice 410 | 411 | /// Try to find the given target assembly in the context 412 | member TryBindSimpleAssemblyNameToTarget: assemblyName: string -> Choice 413 | 414 | /// Get the list of referenced assemblies determined by the type provider configuration 415 | member ReferencedAssemblyPaths: string list 416 | 417 | /// Get the resolved referenced assemblies determined by the type provider configuration 418 | member GetTargetAssemblies : unit -> Assembly[] 419 | 420 | /// Get the set of design-time assemblies available to use as a basis for authoring provided types. 421 | member GetSourceAssemblies : unit -> Assembly[] 422 | 423 | /// Add an assembly to the set of design-time assemblies available to use as a basis for authoring provided types 424 | member AddSourceAssembly : Assembly -> unit 425 | 426 | /// Try to get the version of FSharp.Core referenced. May raise an exception if FSharp.Core has not been correctly resolved 427 | member FSharpCoreAssemblyVersion: Version 428 | 429 | /// Returns a type from the referenced assemblies that corresponds to the given design-time type. Normally 430 | /// this method should not be used directly when authoring a type provider. 431 | member ConvertSourceTypeToTarget: Type -> Type 432 | 433 | /// Returns the design-time type that corresponds to the given type from the target referenced assemblies. Normally 434 | /// this method should not be used directly when authoring a type provider. 435 | member ConvertTargetTypeToSource: Type -> Type 436 | 437 | /// Returns a quotation rebuilt with resepct to the types from the target referenced assemblies. Normally 438 | /// this method should not be used directly when authoring a type provider. 439 | member ConvertSourceExprToTarget: Expr -> Expr 440 | 441 | /// Read the assembly related to this context 442 | member ReadRelatedAssembly: fileName: string -> Assembly 443 | 444 | /// Read the assembly related to this context 445 | member ReadRelatedAssembly: bytes: byte[] -> Assembly 446 | 447 | /// A base type providing default implementations of type provider functionality. 448 | type TypeProviderForNamespaces = 449 | 450 | /// Initializes a type provider to provide the types in the given namespace. 451 | /// 452 | /// Optionally specify the design-time assemblies available to use as a basis for authoring provided types. 453 | /// The transitive dependencies of these assemblies are also included. By default 454 | /// Assembly.GetCallingAssembly() and its transitive dependencies are used. 455 | /// 456 | /// 457 | /// 458 | /// Optionally specify a map of assembly names from source model to referenced assemblies. 459 | /// 460 | /// 461 | /// 462 | /// Optionally specify that the location of the type provider design-time component should be used to resolve failing assembly resolutions. 463 | /// This flag or an equivalent call to RegisterProbingFolder is generally needed for any type provider design-time components loaded into .NET Core tooling. 464 | /// 465 | new: config: TypeProviderConfig * namespaceName:string * types: ProvidedTypeDefinition list * ?sourceAssemblies: Assembly list * ?assemblyReplacementMap: (string * string) list * ?addDefaultProbingLocation: bool -> TypeProviderForNamespaces 466 | 467 | /// Initializes a type provider. 468 | /// 469 | /// Optionally specify the design-time assemblies available to use as a basis for authoring provided types. 470 | /// The transitive dependencies of these assemblies are also included. By default 471 | /// Assembly.GetCallingAssembly() and its transitive dependencies are used. 472 | /// 473 | /// 474 | /// 475 | /// Optionally specify a map of assembly names from source model to referenced assemblies. 476 | /// 477 | /// 478 | /// 479 | /// Optionally specify that the location of the type provider design-time component should be used to resolve failing assembly resolutions. 480 | /// This flag or an equivalent call to RegisterProbingFolder is generally needed for any type provider design-time components loaded into .NET Core tooling. 481 | /// 482 | new: config: TypeProviderConfig * ?sourceAssemblies: Assembly list * ?assemblyReplacementMap: (string * string) list * ?addDefaultProbingLocation: bool -> TypeProviderForNamespaces 483 | 484 | /// Invoked by the type provider to add a namespace of provided types in the specification of the type provider. 485 | member AddNamespace: namespaceName:string * types: ProvidedTypeDefinition list -> unit 486 | 487 | /// Invoked by the type provider to get all provided namespaces with their provided types. 488 | member Namespaces: IProvidedNamespace[] 489 | 490 | /// Invoked by the type provider to invalidate the information provided by the provider 491 | member Invalidate: unit -> unit 492 | 493 | /// Invoked by the host of the type provider to get the static parameters for a method. 494 | member GetStaticParametersForMethod: MethodBase -> ParameterInfo[] 495 | 496 | /// Invoked by the host of the type provider to apply the static argumetns for a method. 497 | member ApplyStaticArgumentsForMethod: MethodBase * string * obj[] -> MethodBase 498 | 499 | #if !FX_NO_LOCAL_FILESYSTEM 500 | /// AssemblyResolve handler. Default implementation searches .dll file in registered folders 501 | abstract ResolveAssembly: ResolveEventArgs -> Assembly 502 | default ResolveAssembly: ResolveEventArgs -> Assembly 503 | 504 | /// Registers custom probing path that can be used for probing assemblies 505 | member RegisterProbingFolder: folder: string -> unit 506 | 507 | /// Registers location of RuntimeAssembly (from TypeProviderConfig) as probing folder 508 | member RegisterRuntimeAssemblyLocationAsProbingFolder: config: TypeProviderConfig -> unit 509 | 510 | #endif 511 | 512 | #if !NO_GENERATIVE 513 | /// Register that a given file is a provided generated target assembly, e.g. an assembly produced by an external 514 | /// code generation tool. This assembly should be a target assembly, i.e. use the same asssembly references 515 | /// as given by TargetContext.ReferencedAssemblyPaths 516 | member RegisterGeneratedTargetAssembly: fileName: string -> Assembly 517 | #endif 518 | 519 | [] 520 | member Disposing: IEvent 521 | 522 | /// The context for which code is eventually to be generated. You should not normally 523 | /// need to use this property directly, as translation from the compiler-hosted context to 524 | /// the design-time context will normally be performed automatically. 525 | member TargetContext: ProvidedTypesContext 526 | 527 | interface ITypeProvider 528 | 529 | 530 | module internal UncheckedQuotations = 531 | 532 | type Expr with 533 | static member NewDelegateUnchecked: ty:Type * vs:Var list * body:Expr -> Expr 534 | static member NewObjectUnchecked: cinfo:ConstructorInfo * args:Expr list -> Expr 535 | static member NewArrayUnchecked: elementType:Type * elements:Expr list -> Expr 536 | static member CallUnchecked: minfo:MethodInfo * args:Expr list -> Expr 537 | static member CallUnchecked: obj:Expr * minfo:MethodInfo * args:Expr list -> Expr 538 | static member ApplicationUnchecked: f:Expr * x:Expr -> Expr 539 | static member PropertyGetUnchecked: pinfo:PropertyInfo * args:Expr list -> Expr 540 | static member PropertyGetUnchecked: obj:Expr * pinfo:PropertyInfo * ?args:Expr list -> Expr 541 | static member PropertySetUnchecked: pinfo:PropertyInfo * value:Expr * ?args:Expr list -> Expr 542 | static member PropertySetUnchecked: obj:Expr * pinfo:PropertyInfo * value:Expr * ?args:Expr list -> Expr 543 | static member FieldGetUnchecked: pinfo:FieldInfo -> Expr 544 | static member FieldGetUnchecked: obj:Expr * pinfo:FieldInfo -> Expr 545 | static member FieldSetUnchecked: pinfo:FieldInfo * value:Expr -> Expr 546 | static member FieldSetUnchecked: obj:Expr * pinfo:FieldInfo * value:Expr -> Expr 547 | static member TupleGetUnchecked: e:Expr * n:int -> Expr 548 | static member LetUnchecked: v:Var * e:Expr * body:Expr -> Expr 549 | 550 | type Shape 551 | val ( |ShapeCombinationUnchecked|ShapeVarUnchecked|ShapeLambdaUnchecked| ): e:Expr -> Choice<(Shape * Expr list),Var, (Var * Expr)> 552 | val RebuildShapeCombinationUnchecked: Shape * args:Expr list -> Expr 553 | 554 | --------------------------------------------------------------------------------
PM> Install-Package FSharp.Text.RegexProvider