This commit is contained in:
nosami 2016-09-24 16:06:08 +01:00
Родитель 5f34c43250
Коммит 76e0f89a31
8 изменённых файлов: 301 добавлений и 0 удалений

40
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,40 @@
# Autosave files
*~
# build
[Oo]bj/
[Bb]in/
packages/
TestResults/
# globs
Makefile.in
*.DS_Store
*.sln.cache
*.suo
*.cache
*.pidb
*.userprefs
*.usertasks
config.log
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.user
*.tar.gz
tarballs/
test-results/
Thumbs.db
# Mac bundle stuff
*.dmg
*.app
# resharper
*_Resharper.*
*.Resharper
# dotCover
*.dotCover

132
ResourceTypeProvider.fs Normal file
Просмотреть файл

@ -0,0 +1,132 @@
namespace Xamarin.Android.FSharp
open System
open System.IO
open System.Reflection
open System.CodeDom.Compiler
open System.Collections.Generic
open Microsoft.CSharp
open FSharp.Quotations
open FSharp.Core.CompilerServices
open Microsoft.FSharp.Core.CompilerServices
[<TypeProvider>]
type ResourceProvider(config : TypeProviderConfig) =
let mutable providedAssembly = None
let invalidate = Event<EventHandler,EventArgs>()
let compiler = new CSharpCodeProvider()
let pathToDesigner = Path.Combine(config.ResolutionFolder, "Resources")
// watcher doesn't trigger when I specify the filename exactly
let watcher = new FileSystemWatcher(pathToDesigner, "*.fs", EnableRaisingEvents=true)
let generate sourceCode =
let guid = Guid.NewGuid() |> string
let asm = sprintf "ProvidedTypes%s.dll" (Guid.NewGuid() |> string)
let cp = CompilerParameters(
GenerateInMemory = false,
OutputAssembly = Path.Combine(config.TemporaryFolder, asm),
TempFiles = new TempFileCollection(config.TemporaryFolder, false),
CompilerOptions = "/nostdlib /noconfig")
let addReference assemblyFileName =
printfn "Adding reference %s" assemblyFileName
let reference =
config.ReferencedAssemblies |> Array.tryFind(fun r -> r.EndsWith(assemblyFileName, StringComparison.InvariantCultureIgnoreCase)
&& r.IndexOf("Facade") = -1)
match reference with
| Some ref -> cp.ReferencedAssemblies.Add ref |> ignore
(Some ref, assemblyFileName)
| None -> printfn "Did not find %s in referenced assemblies." assemblyFileName
None, assemblyFileName
printfn "F# Android resource provider"
let android = addReference "Mono.Android.dll"
let system = addReference "System.dll"
let mscorlib = addReference "mscorlib.dll"
let addIfMissingReference addResult =
match android, addResult with
| (Some androidRef, _), (None, assemblyFileName) ->
// When the TP is ran from XS, config.ReferencedAssemblies doesn't contain mscorlib or System.dll
// but from xbuild, it does. Need to investigate why.
let systemPath = Path.GetDirectoryName androidRef
cp.ReferencedAssemblies.Add(Path.Combine(systemPath, "..", "v1.0", assemblyFileName)) |> ignore
| _, _ -> ()
addIfMissingReference system
addIfMissingReference mscorlib
let result = compiler.CompileAssemblyFromSource(cp, [| sourceCode |])
if result.Errors.HasErrors then
printfn "%A" result.Errors
failwithf "%A" result.Errors
let asm = Assembly.ReflectionOnlyLoadFrom cp.OutputAssembly
let types = asm.GetTypes()
let namespaces =
let dict = Dictionary<_,List<_>>()
for t in types do
printfn "%A" t
let namespc = if isNull t.Namespace then "global" else t.Namespace
match dict.TryGetValue(namespc) with
| true, ns -> ns.Add(t)
| _, _ ->
let ns = List<_>()
ns.Add(t)
dict.Add(namespc, ns)
dict
|> Seq.map (fun kv ->
{ new IProvidedNamespace with
member x.NamespaceName = kv.Key
member x.GetNestedNamespaces() = [||] //FIXME
member x.GetTypes() = kv.Value.ToArray()
member x.ResolveTypeName(typeName: string) = null
}
)
|> Seq.toArray
providedAssembly <- Some(File.ReadAllBytes(result.PathToAssembly), namespaces)
do
watcher.Changed.Add(fun _ -> printfn "Invalidating resources"; invalidate.Trigger(null, null))
let source = File.ReadAllText(Path.Combine(pathToDesigner, "Resource.designer.fs"))
AppDomain.CurrentDomain.add_ReflectionOnlyAssemblyResolve(fun _ args ->
let name = AssemblyName(args.Name)
printfn "Resolving %s" args.Name
let existingAssembly =
AppDomain.CurrentDomain.GetAssemblies()
|> Seq.tryFind(fun a -> AssemblyName.ReferenceMatchesDefinition(name, a.GetName()))
let asm =
match existingAssembly with
| Some a -> printfn "Resolved to %s" a.Location
a
| None -> null
asm)
generate source
interface ITypeProvider with
[<CLIEvent>]
member x.Invalidate = invalidate.Publish
member x.GetStaticParameters(typeWithoutArguments) = [||]
member x.GetGeneratedAssemblyContents(assembly) =
match providedAssembly with
| Some(bytes, _) -> bytes
| _ -> failwith "Generate was never called"
member x.GetNamespaces() =
match providedAssembly with
| Some(_, namespaces) -> namespaces
| _ -> failwith "Generate was never called"
member x.ApplyStaticArguments(typeWithoutArguments, typeNameWithArguments, staticArguments) = null
member x.GetInvokerExpression(mb, parameters) = Expr.Call(mb :?> MethodInfo, Array.toList parameters)
member x.Dispose() =
compiler.Dispose()
watcher.Dispose()
[<assembly: TypeProviderAssembly>]
do()

5
Runtime/Provider.fs Normal file
Просмотреть файл

@ -0,0 +1,5 @@
namespace Xamarin.Android.FSharp
open Microsoft.FSharp.Core.CompilerServices
[<assembly:TypeProviderAssembly("Xamarin.Android.FSharp.ResourceProvider")>]
()

Просмотреть файл

Просмотреть файл

@ -0,0 +1,55 @@
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8307D8BE-EFF7-459D-900D-8D2D83C7653B}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{F2A71F9B-5D33-465A-A702-920D77279786}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>Xamarin.Android.FSharp</RootNamespace>
<AssemblyName>
Xamarin.Android.FSharp.ResourceProvider.Runtime</AssemblyName>
<TargetFrameworkVersion>v7.0</TargetFrameworkVersion>
<AndroidResgenFile>Resources\Resource.designer.fs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<AndroidLinkMode>None</AndroidLinkMode>
<PlatformTarget></PlatformTarget>
<AndroidSupportedAbis>arm64-v8a;armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin</OutputPath>
<DefineConstants></DefineConstants>
<ErrorReport>prompt</ErrorReport>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<GenerateTailCalls>true</GenerateTailCalls>
<PlatformTarget></PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core">
<HintPath>..\packages\FSharp.Core.4.0.0.1\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="Provider.fs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.FSharp.targets" />
<Import Project="..\packages\Xamarin.Android.Support.Vector.Drawable.23.4.0.1\build\Xamarin.Android.Support.Vector.Drawable.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Vector.Drawable.23.4.0.1\build\Xamarin.Android.Support.Vector.Drawable.targets')" />
</Project>

4
Runtime/packages.config Normal file
Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.0.0.1" targetFramework="monoandroid70" />
</packages>

Просмотреть файл

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F0B64BEE-BBAA-4A11-94F8-DBE1A9C04D11}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Xamarin.Android.FSharp</RootNamespace>
<AssemblyName>Xamarin.Android.FSharp.ResourceProvider</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<PlatformTarget></PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin</OutputPath>
<DefineConstants></DefineConstants>
<ErrorReport>prompt</ErrorReport>
<GenerateTailCalls>true</GenerateTailCalls>
<PlatformTarget></PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0' OR '$(VisualStudioVersion)' == '11.0'">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="ResourceTypeProvider.fs" />
</ItemGroup>
<Import Project="$(FSharpTargetsPath)" />
</Project>

Просмотреть файл

@ -0,0 +1,23 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "Xamarin.Android.FSharp.ResourceProvider", "Xamarin.Android.FSharp.ResourceProvider.fsproj", "{F0B64BEE-BBAA-4A11-94F8-DBE1A9C04D11}"
EndProject
Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "Xamarin.Android.FSharp.ResourceProvider.Runtime", "Runtime\Xamarin.Android.FSharp.ResourceProvider.Runtime.fsproj", "{8307D8BE-EFF7-459D-900D-8D2D83C7653B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F0B64BEE-BBAA-4A11-94F8-DBE1A9C04D11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0B64BEE-BBAA-4A11-94F8-DBE1A9C04D11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0B64BEE-BBAA-4A11-94F8-DBE1A9C04D11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0B64BEE-BBAA-4A11-94F8-DBE1A9C04D11}.Release|Any CPU.Build.0 = Release|Any CPU
{8307D8BE-EFF7-459D-900D-8D2D83C7653B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8307D8BE-EFF7-459D-900D-8D2D83C7653B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8307D8BE-EFF7-459D-900D-8D2D83C7653B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8307D8BE-EFF7-459D-900D-8D2D83C7653B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal