-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathJavaTypeProvider.fs
More file actions
83 lines (69 loc) · 2.99 KB
/
JavaTypeProvider.fs
File metadata and controls
83 lines (69 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
namespace Java
open System
open System.IO
open System.Reflection
open System.Reflection.Emit
open System.Collections.Generic
open System.Diagnostics
open Microsoft.FSharp.Core.CompilerServices
open Samples.FSharp.ProvidedTypes
open Microsoft.FSharp.Quotations
type Cache private () =
static let mutable instance = Dictionary<_, _>()
static member Instance = instance
module Helpers =
let memoize f =
fun n ->
match Cache.Instance.TryGetValue(n) with
| (true, v) -> v
| _ ->
let temp = f(n)
Cache.Instance.Add(n, temp)
temp
let fullPath (config :TypeProviderConfig) path =
if Path.IsPathRooted(path)
then path
else Path.Combine(config.ResolutionFolder, path)
let watchForChanges invalidate (fileName:string) =
let w = new FileSystemWatcher(Filter = Path.GetFileName(fileName), Path = Path.GetDirectoryName(fileName))
w.Changed.Add(fun _ -> invalidate())
w.EnableRaisingEvents <- true
[<TypeProvider>]
type public JavaTypeProvider(config: TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
let thisAssembly = Assembly.GetExecutingAssembly()
let rootNamespace = "Java"
let dir = IO.Path.GetDirectoryName(config.RuntimeAssembly)
let baseType = typeof<obj>
let staticParams =
[
ProvidedStaticParameter("JarFile", typeof<string>)
ProvidedStaticParameter("IKVMPath", typeof<string>, Path.Combine(config.ResolutionFolder, "IKVM"))
]
let containerType = ProvidedTypeDefinition(thisAssembly, rootNamespace, "JavaProvider", Some(baseType), IsErased = false)
let invalidate key = (fun () ->
if Cache.Instance.Remove(key)
then
GlobalProvidedAssemblyElementsTable.theTable.Clear()
this.Invalidate()
)
let loader (typeName, jarFile, ikvmPath) =
this.RegisterProbingFolder(ikvmPath)
this.RegisterProbingFolder(Path.GetDirectoryName(jarFile))
let assemblyBytes = IKVMCompiler.compile ikvmPath config.TemporaryFolder jarFile
let assembly = Assembly.Load(assemblyBytes)
GlobalProvidedAssemblyElementsTable.theTable.[assembly] <- assemblyBytes
let t = ProvidedTypeDefinition(thisAssembly, rootNamespace, typeName, Some(baseType), IsErased = false)
t.AddAssemblyTypesAsNestedTypesDelayed (fun _ -> assembly) false
t
do containerType.DefineStaticParameters(
staticParams,
(fun typeName [| :? string as jarFile ; :? string as ikvmPath|] ->
let jar, ikvm = Helpers.fullPath config jarFile, Helpers.fullPath config ikvmPath
Helpers.watchForChanges (invalidate (typeName, jar, ikvm)) jar
Helpers.memoize loader (typeName, jar, ikvm)
))
do
this.AddNamespace(rootNamespace, [containerType])
[<TypeProviderAssembly>]
do()