From 01c467466abfd10cb0aee50fa58b7acff9f3aae0 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Fri, 15 Sep 2017 16:21:47 -0700 Subject: [PATCH 01/16] add build task to generate *.fs from *.resx files --- src/FSharpSource.targets | 20 +++- .../FSharp.Build-proto.fsproj | 4 + .../FSharp.Build.BuildFromSource.fsproj | 1 + src/fsharp/FSharp.Build/FSharp.Build.fsproj | 2 + .../FSharp.Build/FSharpEmbedResXSource.fs | 111 ++++++++++++++++++ .../FSharp.Build/Microsoft.FSharp.Targets | 18 ++- src/fsharp/FSharp.Core/FSCore.resx | 2 +- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 17 +-- src/fsharp/FSharp.Core/Query.fs | 24 ++-- src/fsharp/FSharp.Core/SR.fs | 7 -- src/fsharp/FSharp.Core/prim-types.fs | 2 +- src/fsharp/FSharp.Core/quotations.fs | 24 ++-- src/fsharp/FSharp.Core/reflect.fs | 38 +++--- 13 files changed, 205 insertions(+), 65 deletions(-) create mode 100644 src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs diff --git a/src/FSharpSource.targets b/src/FSharpSource.targets index ef32269142f..869b0a8a689 100644 --- a/src/FSharpSource.targets +++ b/src/FSharpSource.targets @@ -360,6 +360,9 @@ + + + + + + + + + + + + - + - + - + diff --git a/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj b/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj index be84e9738e6..c5c361ca1d2 100644 --- a/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj +++ b/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj @@ -37,6 +37,9 @@ FSharpEmbedResourceText.fs + + FSharpEmbedResXSource.fs + Microsoft.FSharp-proto.targets Microsoft.FSharp-proto.targets @@ -67,6 +70,7 @@ + diff --git a/src/fsharp/FSharp.Build/FSharp.Build.BuildFromSource.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.BuildFromSource.fsproj index 58670adc78f..2357356794d 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.BuildFromSource.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.BuildFromSource.fsproj @@ -22,6 +22,7 @@ + diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 8117fccc927..30aeb96da5b 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -31,6 +31,7 @@ + @@ -59,6 +60,7 @@ + diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs new file mode 100644 index 00000000000..790a296d495 --- /dev/null +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Build + +open System +open System.Collections +open System.Globalization +open System.IO +open System.Linq +open System.Text +open System.Xml.Linq +open Microsoft.Build.Framework +open Microsoft.Build.Utilities + +type FSharpEmbedResXSource() = + let mutable _buildEngine : IBuildEngine = null + let mutable _hostObject : ITaskHost = null + let mutable _embeddedText : ITaskItem[] = [||] + let mutable _generatedSource : ITaskItem[] = [||] + let mutable _outputPath : string = "" + + let boilerplate = @"// + +namespace {0} + +open System.Reflection + +module internal {1} = + type private C (_dummy:System.Object) = class end + let mutable Culture = System.Globalization.CultureInfo.CurrentUICulture + let ResourceManager = new System.Resources.ResourceManager(""{2}"", C(null).GetType().GetTypeInfo().Assembly) + let GetString(name:System.String) : System.String = ResourceManager.GetString(name, Culture)" + + let generateSource (resx:string) (fullModuleName:string) (generateLegacy:bool) = + try + let printMessage = printfn "FSharpEmbedResXSource: %s" + let justFileName = Path.GetFileNameWithoutExtension(resx) + let namespaceName, moduleName = + let parts = fullModuleName.Split('.') + if parts.Length = 1 then ("global", parts.[0]) + else (String.Join(".", parts, 0, parts.Length - 1), parts.[parts.Length - 1]) + let sb = StringBuilder().AppendLine(String.Format(boilerplate, namespaceName, moduleName, justFileName)) + let sourcePath = Path.Combine(_outputPath, justFileName + ".fs") + printMessage <| sprintf "Generating: %s" sourcePath + let body = + XDocument.Load(resx).Descendants(XName.op_Implicit "data") + |> Seq.fold (fun (sb:StringBuilder) (node:XElement) -> + let name = + match node.Attribute(XName.op_Implicit "name") with + | null -> failwith "Missing resource name" + | attr -> attr.Value + let docComment = + match node.Elements(XName.op_Implicit "value").FirstOrDefault() with + | null -> failwith <| sprintf "Missing resource value for '%s'" name + | element -> element.Value.Trim() + let identifier = if Char.IsLetter(name.[0]) || name.[0] = '_' then name else "_" + name + let commentBody = + XElement(XName.op_Implicit "summary", docComment).ToString().Split([|"\r\n"; "\r"; "\n"|], StringSplitOptions.None) + |> Array.fold (fun (sb:StringBuilder) line -> sb.AppendLine(" /// " + line)) (StringBuilder()) + // add the resource + let accessorBody = + if generateLegacy then sprintf " let %s = \"%s\"" identifier name + else sprintf " let %s() = GetString(\"%s\")" identifier name + sb.AppendLine().Append(commentBody).AppendLine(accessorBody) + ) sb + File.WriteAllText(sourcePath, body.ToString()) + printMessage <| sprintf "Done: %s" sourcePath + Some(sourcePath) + with e -> + printf "An exception occurred when processing '%s'\n%s" resx (e.ToString()) + None + + [] + member this.EmbeddedResource + with get() = _embeddedText + and set(value) = _embeddedText <- value + + [] + member this.IntermediateOutputPath + with get() = _outputPath + and set(value) = _outputPath <- value + + [] + member this.GeneratedSource + with get() = _generatedSource + + interface ITask with + member this.BuildEngine + with get() = _buildEngine + and set(value) = _buildEngine <- value + member this.HostObject + with get() = _hostObject + and set(value) = _hostObject <- value + member this.Execute() = + let getBooleanMetadata (metadataName:string) (item:ITaskItem) = String.Compare(item.GetMetadata(metadataName), "true", StringComparison.OrdinalIgnoreCase) = 0 + let generatedFiles, generatedResult = + this.EmbeddedResource + |> Array.filter (getBooleanMetadata "GenerateSource") + |> Array.fold (fun (resultList, aggregateResult) item -> + let moduleName = + match item.GetMetadata("GeneratedModuleName") with + | null -> Path.GetFileNameWithoutExtension(item.ItemSpec) + | value -> value + let generateLegacy = getBooleanMetadata "GenerateLegacyCode" item + match generateSource item.ItemSpec moduleName generateLegacy with + | Some (source) -> ((source :: resultList), aggregateResult) + | None -> (resultList, false) + ) ([], true) + let generatedSources = generatedFiles |> List.map (fun item -> TaskItem(item) :> ITaskItem) + _generatedSource <- generatedSources |> List.rev |> List.toArray + generatedResult diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index 1776fadd3d6..b7165c57868 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -23,6 +23,7 @@ this file. + @@ -175,15 +176,26 @@ this file. + + + + + + + + + + + - + - + - + diff --git a/src/fsharp/FSharp.Core/FSCore.resx b/src/fsharp/FSharp.Core/FSCore.resx index 9df009a38b1..8b74b1d039c 100644 --- a/src/fsharp/FSharp.Core/FSCore.resx +++ b/src/fsharp/FSharp.Core/FSCore.resx @@ -501,7 +501,7 @@ type argument out of range - + This value cannot be mutated diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 204f628733d..4e7fe386fca 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -50,16 +50,19 @@ + + Primitives/prim-types-prelude.fsi + + + Primitives/prim-types-prelude.fs + + true + true + Microsoft.FSharp.Core.SR FSCore.resx - - Primitives/prim-types-prelude.fsi - - - Primitives/prim-types-prelude.fs - - + Primitives/SR.fs diff --git a/src/fsharp/FSharp.Core/Query.fs b/src/fsharp/FSharp.Core/Query.fs index 87735bfeead..fbab2547ed3 100644 --- a/src/fsharp/FSharp.Core/Query.fs +++ b/src/fsharp/FSharp.Core/Query.fs @@ -1418,41 +1418,41 @@ module Query = TransInnerResult.Source(expr), NoConv | Call (_, meth, _) when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryCall,meth.ToString()))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryCall),meth.ToString()))) | PropertyGet (_, pinfo, _) when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryProperty,pinfo.ToString()))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryProperty),pinfo.ToString()))) | NewObject(ty,_) when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstructKind,"new " + ty.ToString()))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstructKind),"new " + ty.ToString()))) | NewArray(ty,_) when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstructKind,"NewArray(" + ty.Name + ",...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstructKind),"NewArray(" + ty.Name + ",...)"))) | NewTuple _ when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstructKind,"NewTuple(...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstructKind),"NewTuple(...)"))) | FieldGet (_,field) when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstructKind,"FieldGet(" + field.Name + ",...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstructKind),"FieldGet(" + field.Name + ",...)"))) | LetRecursive _ when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstruct,"LetRecursive(...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstruct),"LetRecursive(...)"))) | NewRecord _ when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstruct,"NewRecord(...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstruct),"NewRecord(...)"))) | NewDelegate _ when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstruct,"NewDelegate(...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstruct),"NewDelegate(...)"))) | NewTuple _ when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstruct,"NewTuple(...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstruct),"NewTuple(...)"))) | NewUnionCase (ucase,_) when check -> - raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstruct,"NewUnionCase(" + ucase.Name + "...)"))) + raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstruct),"NewUnionCase(" + ucase.Name + "...)"))) // Error cases | e -> - if check then raise (NotSupportedException (SR.GetString1(SR.unsupportedQueryConstruct,immutQuery.ToString()))) + if check then raise (NotSupportedException (String.Format(SR.GetString(SR.unsupportedQueryConstruct),immutQuery.ToString()))) else TransInnerResult.Source(e),NoConv diff --git a/src/fsharp/FSharp.Core/SR.fs b/src/fsharp/FSharp.Core/SR.fs index 70ec3e94cb4..278eb5d88fd 100644 --- a/src/fsharp/FSharp.Core/SR.fs +++ b/src/fsharp/FSharp.Core/SR.fs @@ -161,10 +161,3 @@ module internal SR = let GetString(name:System.String) : System.String = resources.GetString(name, System.Globalization.CultureInfo.CurrentUICulture) - let GetString1(name:System.String, arg1:System.String) : System.String = - System.String.Format(resources.GetString(name, System.Globalization.CultureInfo.CurrentUICulture), arg1) - let GetString2(name:System.String, arg1:System.String, arg2:System.String) : System.String = - System.String.Format(resources.GetString(name, System.Globalization.CultureInfo.CurrentUICulture), arg1, arg2) - let GetString3(name:System.String, arg1:System.String, arg2:System.String, arg3:System.String) : System.String = - System.String.Format(resources.GetString(name, System.Globalization.CultureInfo.CurrentUICulture), arg1, arg2, arg3) - diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index bfe1a6af3dc..18e8539fc3c 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -804,7 +804,7 @@ namespace Microsoft.FSharp.Core //------------------------------------------------------------------------- let FailGenericComparison (obj: obj) = - raise (new System.ArgumentException(SR.GetString1(SR.genericCompareFail1, obj.GetType().ToString()))) + raise (new System.ArgumentException(String.Format(SR.GetString(SR.genericCompareFail1), obj.GetType().ToString()))) /// This type has two instances - fsComparerER and fsComparerThrow. diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index 35dbcadb2b5..a520286e0cf 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -576,13 +576,13 @@ module Patterns = let mems = FSharpType.GetRecordFields(ty,publicOrPrivateBindingFlags) match mems |> Array.tryFind (fun minfo -> minfo.Name = fieldName) with | Some (m) -> m - | _ -> invalidArg "fieldName" (SR.GetString2(SR.QmissingRecordField, ty.FullName, fieldName)) + | _ -> invalidArg "fieldName" (String.Format(SR.GetString(SR.QmissingRecordField), ty.FullName, fieldName)) let getUnionCaseInfo(ty,unionCaseName) = let cases = FSharpType.GetUnionCases(ty,publicOrPrivateBindingFlags) match cases |> Array.tryFind (fun ucase -> ucase.Name = unionCaseName) with | Some(case) -> case - | _ -> invalidArg "unionCaseName" (SR.GetString2(SR.QmissingUnionCase, ty.FullName, unionCaseName)) + | _ -> invalidArg "unionCaseName" (String.Format(SR.GetString(SR.QmissingUnionCase), ty.FullName, unionCaseName)) let getUnionCaseInfoField(unionCase:UnionCaseInfo,index) = let fields = unionCase.GetFields() @@ -708,7 +708,7 @@ module Patterns = let cases = FSharpType.GetUnionCases(ty,publicOrPrivateBindingFlags) match cases |> Array.tryFind (fun ucase -> ucase.Name = str) with | Some(case) -> case.GetFields() - | _ -> invalidArg "ty" (SR.GetString1(SR.notAUnionType, ty.FullName)) + | _ -> invalidArg "ty" (String.Format(SR.GetString(SR.notAUnionType), ty.FullName)) let checkBind(v:Var,e) = let ety = typeOf e @@ -1006,14 +1006,14 @@ module Patterns = let bindModuleProperty (ty:Type,nm) = match ty.GetProperty(nm,staticBindingFlags) with - | null -> raise <| System.InvalidOperationException (SR.GetString2(SR.QcannotBindProperty, nm, ty.ToString())) + | null -> raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindProperty), nm, ty.ToString())) | res -> res // tries to locate unique function in a given type // in case of multiple candidates returns None so bindModuleFunctionWithCallSiteArgs will be used for more precise resolution let bindModuleFunction (ty:Type,nm) = match ty.GetMethods(staticBindingFlags) |> Array.filter (fun mi -> mi.Name = nm) with - | [||] -> raise <| System.InvalidOperationException (SR.GetString2(SR.QcannotBindFunction, nm, ty.ToString())) + | [||] -> raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindFunction), nm, ty.ToString())) | [| res |] -> Some res | _ -> None @@ -1042,7 +1042,7 @@ module Patterns = let methodTyArgCount = if mi.IsGenericMethod then mi.GetGenericArguments().Length else 0 methodTyArgCount = tyArgs.Length ) - let fail() = raise <| System.InvalidOperationException (SR.GetString2(SR.QcannotBindFunction, nm, ty.ToString())) + let fail() = raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.QcannotBindFunction), nm, ty.ToString())) match candidates with | [||] -> fail() | [| solution |] -> solution @@ -1150,13 +1150,13 @@ module Patterns = typ.GetProperty(propName, staticOrInstanceBindingFlags) with :? AmbiguousMatchException -> null // more than one property found with the specified name and matching binding constraints - return null to initiate manual search |> bindPropBySearchIfCandidateIsNull typ propName retType (Array.ofList argtyps) - |> checkNonNullResult ("propName", SR.GetString1(SR.QfailedToBindProperty, propName)) // fxcop may not see "propName" as an arg + |> checkNonNullResult ("propName", String.Format(SR.GetString(SR.QfailedToBindProperty), propName)) // fxcop may not see "propName" as an arg #else - typ.GetProperty(propName, staticOrInstanceBindingFlags, null, retType, Array.ofList argtyps, null) |> checkNonNullResult ("propName", SR.GetString1(SR.QfailedToBindProperty, propName)) // fxcop may not see "propName" as an arg + typ.GetProperty(propName, staticOrInstanceBindingFlags, null, retType, Array.ofList argtyps, null) |> checkNonNullResult ("propName", String.Format(SR.GetString(SR.QfailedToBindProperty), propName)) // fxcop may not see "propName" as an arg #endif let bindField (tc,fldName,tyargs) = let typ = mkNamedType(tc,tyargs) - typ.GetField(fldName,staticOrInstanceBindingFlags) |> checkNonNullResult ("fldName", SR.GetString1(SR.QfailedToBindField, fldName)) // fxcop may not see "fldName" as an arg + typ.GetField(fldName,staticOrInstanceBindingFlags) |> checkNonNullResult ("fldName", String.Format(SR.GetString(SR.QfailedToBindField), fldName)) // fxcop may not see "fldName" as an arg let bindGenericCctor (tc:Type) = tc.GetConstructor(staticBindingFlags,null,[| |],null) @@ -1328,7 +1328,7 @@ module Patterns = // For some reason we can get 'null' returned here even when a type with the right name exists... Hence search the slow way... match (ass.GetTypes() |> Array.tryFind (fun a -> a.FullName = tcName)) with | Some ty -> ty - | None -> invalidArg "tcName" (SR.GetString2(SR.QfailedToBindTypeInAssembly, tcName, ass.FullName)) // "Available types are:\n%A" tcName ass (ass.GetTypes() |> Array.map (fun a -> a.FullName)) + | None -> invalidArg "tcName" (String.Format(SR.GetString(SR.QfailedToBindTypeInAssembly), tcName, ass.FullName)) // "Available types are:\n%A" tcName ass (ass.GetTypes() |> Array.map (fun a -> a.FullName)) | ty -> ty let decodeNamedTy tc tsR = mkNamedType(tc,tsR) @@ -1344,7 +1344,7 @@ module Patterns = #else match System.Reflection.Assembly.Load(a) with #endif - | null -> raise <| System.InvalidOperationException(SR.GetString1(SR.QfailedToBindAssembly, a.ToString())) + | null -> raise <| System.InvalidOperationException(String.Format(SR.GetString(SR.QfailedToBindAssembly), a.ToString())) | ass -> ass let u_NamedType st = @@ -1863,7 +1863,7 @@ module Patterns = | :? MethodInfo as minfo -> if minfo.IsGenericMethod then minfo.GetGenericArguments().Length else 0 | _ -> 0) if (expectedNumTypars <> tyargs.Length) then - invalidArg "tyargs" (SR.GetString3(SR.QwrongNumOfTypeArgs, methodBase.Name, expectedNumTypars.ToString(), tyargs.Length.ToString())); + invalidArg "tyargs" (String.Format(SR.GetString(SR.QwrongNumOfTypeArgs), methodBase.Name, expectedNumTypars.ToString(), tyargs.Length.ToString())); Some(exprBuilder (envClosed tyargs)) | None -> None diff --git a/src/fsharp/FSharp.Core/reflect.fs b/src/fsharp/FSharp.Core/reflect.fs index 2f20c4c35b4..4c69ddca0b3 100644 --- a/src/fsharp/FSharp.Core/reflect.fs +++ b/src/fsharp/FSharp.Core/reflect.fs @@ -332,7 +332,7 @@ module internal Impl = else "New" + constrname match typ.GetMethod(methname, BindingFlags.Static ||| bindingFlags) with - | null -> raise <| System.InvalidOperationException (SR.GetString1(SR.constructorForUnionCaseNotFound, methname)) + | null -> raise <| System.InvalidOperationException (String.Format(SR.GetString(SR.constructorForUnionCaseNotFound), methname)) | meth -> meth let getUnionCaseConstructor (typ:Type,tag:int,bindingFlags) = @@ -347,9 +347,9 @@ module internal Impl = checkNonNull "unionType" unionType; if not (isUnionType (unionType,bindingFlags)) then if isUnionType (unionType,bindingFlags ||| BindingFlags.NonPublic) then - invalidArg "unionType" (SR.GetString1(SR.privateUnionType, unionType.FullName)) + invalidArg "unionType" (String.Format(SR.GetString(SR.privateUnionType), unionType.FullName)) else - invalidArg "unionType" (SR.GetString1(SR.notAUnionType, unionType.FullName)) + invalidArg "unionType" (String.Format(SR.GetString(SR.notAUnionType), unionType.FullName)) //----------------------------------------------------------------- // TUPLE DECOMPILATION @@ -435,7 +435,7 @@ module internal Impl = | _ -> invalidArg "tys" (SR.GetString(SR.invalidTupleTypes)) let rec getTupleTypeInfo (typ:Type) = - if not (isTupleType (typ) ) then invalidArg "typ" (SR.GetString1(SR.notATupleType, typ.FullName)); + if not (isTupleType (typ) ) then invalidArg "typ" (String.Format(SR.GetString(SR.notATupleType), typ.FullName)); let tyargs = typ.GetGenericArguments() if tyargs.Length = maxTuple then let tysA = tyargs.[0..tupleEncField-1] @@ -507,7 +507,7 @@ module internal Impl = typ.GetConstructor(BindingFlags.Instance ||| bindingFlags,null,props |> Array.map (fun p -> p.PropertyType),null) #endif match ctor with - | null -> raise <| ArgumentException(SR.GetString1(SR.invalidTupleTypeConstructorNotDefined, typ.FullName)) + | null -> raise <| ArgumentException(String.Format(SR.GetString(SR.invalidTupleTypeConstructorNotDefined), typ.FullName)) | _ -> () ctor @@ -561,16 +561,16 @@ module internal Impl = maker1,Some(etys.[tupleEncField]) let getTupleReaderInfo (typ:Type,index:int) = - if index < 0 then invalidArg "index" (SR.GetString2(SR.tupleIndexOutOfRange, typ.FullName, index.ToString())) + if index < 0 then invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString())) let get index = if typ.IsValueType then let props = typ.GetProperties(instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties - if index >= props.Length then invalidArg "index" (SR.GetString2(SR.tupleIndexOutOfRange, typ.FullName, index.ToString())) + if index >= props.Length then invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString())) props.[index] else let props = typ.GetProperties(instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties - if index >= props.Length then invalidArg "index" (SR.GetString2(SR.tupleIndexOutOfRange, typ.FullName, index.ToString())) + if index >= props.Length then invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString())) props.[index] if index < tupleEncField then @@ -584,7 +584,7 @@ module internal Impl = let getFunctionTypeInfo (typ:Type) = - if not (isFunctionType typ) then invalidArg "typ" (SR.GetString1(SR.notAFunctionType, typ.FullName)) + if not (isFunctionType typ) then invalidArg "typ" (String.Format(SR.GetString(SR.notAFunctionType), typ.FullName)) let tyargs = typ.GetGenericArguments() tyargs.[0], tyargs.[1] @@ -632,7 +632,7 @@ module internal Impl = let ctor = typ.GetConstructor(BindingFlags.Instance ||| bindingFlags,null,props |> Array.map (fun p -> p.PropertyType),null) #endif match ctor with - | null -> raise <| ArgumentException(SR.GetString1(SR.invalidRecordTypeConstructorNotDefined, typ.FullName)) + | null -> raise <| ArgumentException(String.Format(SR.GetString(SR.invalidRecordTypeConstructorNotDefined), typ.FullName)) | _ -> () ctor @@ -676,21 +676,21 @@ module internal Impl = let checkExnType (exceptionType, bindingFlags) = if not (isExceptionRepr (exceptionType,bindingFlags)) then if isExceptionRepr (exceptionType,bindingFlags ||| BindingFlags.NonPublic) then - invalidArg "exceptionType" (SR.GetString1(SR.privateExceptionType, exceptionType.FullName)) + invalidArg "exceptionType" (String.Format(SR.GetString(SR.privateExceptionType), exceptionType.FullName)) else - invalidArg "exceptionType" (SR.GetString1(SR.notAnExceptionType, exceptionType.FullName)) + invalidArg "exceptionType" (String.Format(SR.GetString(SR.notAnExceptionType), exceptionType.FullName)) let checkRecordType(argName,recordType,bindingFlags) = checkNonNull argName recordType; if not (isRecordType (recordType,bindingFlags) ) then if isRecordType (recordType,bindingFlags ||| BindingFlags.NonPublic) then - invalidArg argName (SR.GetString1(SR.privateRecordType, recordType.FullName)) + invalidArg argName (String.Format(SR.GetString(SR.privateRecordType), recordType.FullName)) else - invalidArg argName (SR.GetString1(SR.notARecordType, recordType.FullName)) + invalidArg argName (String.Format(SR.GetString(SR.notARecordType), recordType.FullName)) let checkTupleType(argName,(tupleType:Type)) = checkNonNull argName tupleType; - if not (isTupleType tupleType) then invalidArg argName (SR.GetString1(SR.notATupleType, tupleType.FullName)) + if not (isTupleType tupleType) then invalidArg argName (String.Format(SR.GetString(SR.notATupleType), tupleType.FullName)) #if FX_RESHAPED_REFLECTION open ReflectionAdapters @@ -862,7 +862,7 @@ type FSharpValue = static member MakeFunction(functionType:Type,implementation:(obj->obj)) = Impl.checkNonNull "functionType" functionType - if not (Impl.isFunctionType functionType) then invalidArg "functionType" (SR.GetString1(SR.notAFunctionType, functionType.FullName)); + if not (Impl.isFunctionType functionType) then invalidArg "functionType" (String.Format(SR.GetString(SR.notAFunctionType), functionType.FullName)); Impl.checkNonNull "implementation" implementation let domain,range = Impl.getFunctionTypeInfo functionType let dynCloMakerTy = typedefof> @@ -879,15 +879,15 @@ type FSharpValue = static member GetTupleFields(tuple:obj) = // argument name(s) used in error message Impl.checkNonNull "tuple" tuple let typ = tuple.GetType() - if not (Impl.isTupleType typ ) then invalidArg "tuple" (SR.GetString1(SR.notATupleType, tuple.GetType().FullName)); + if not (Impl.isTupleType typ ) then invalidArg "tuple" (String.Format(SR.GetString(SR.notATupleType), tuple.GetType().FullName)); Impl.getTupleReader typ tuple static member GetTupleField(tuple:obj,index:int) = // argument name(s) used in error message Impl.checkNonNull "tuple" tuple let typ = tuple.GetType() - if not (Impl.isTupleType typ ) then invalidArg "tuple" (SR.GetString1(SR.notATupleType, tuple.GetType().FullName)); + if not (Impl.isTupleType typ ) then invalidArg "tuple" (String.Format(SR.GetString(SR.notATupleType), tuple.GetType().FullName)); let fields = Impl.getTupleReader typ tuple - if index < 0 || index >= fields.Length then invalidArg "index" (SR.GetString2(SR.tupleIndexOutOfRange, tuple.GetType().FullName, index.ToString())); + if index < 0 || index >= fields.Length then invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), tuple.GetType().FullName, index.ToString())); fields.[index] static member PreComputeTupleReader(tupleType:Type) : (obj -> obj[]) = From 67295f79190f67cce9b8a13bfe2bd683e6c61020 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 18 Sep 2017 14:30:56 -0700 Subject: [PATCH 02/16] generate source for embedded resources in tests --- .../Sample_VS2012_FSharp_ConsoleApp_net45.fsproj | 10 ++++++++-- .../Sample_VS2012_FSharp_ConsoleApp_net45.fsproj | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj b/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj index ff706fae876..af8a37021ce 100644 --- a/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj +++ b/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj @@ -137,8 +137,11 @@ - + + true + + true The.Explicit.Name.Of.ResxResourceWithLogicalName @@ -150,8 +153,11 @@ - + + true + + true The.Explicit.Name.Of.ResxResourceWithLogicalNameInSubDir diff --git a/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource_using_bootstrap/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj b/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource_using_bootstrap/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj index 447c4c5d528..c2104e72a0b 100644 --- a/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource_using_bootstrap/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj +++ b/tests/projects/Sample_VS2012_FSharp_ConsoleApp_net45_with_resource_using_bootstrap/Sample_VS2012_FSharp_ConsoleApp_net45/Sample_VS2012_FSharp_ConsoleApp_net45.fsproj @@ -59,8 +59,11 @@ - + + true + + true The.Explicit.Name.Of.ResxResourceWithLogicalName @@ -72,8 +75,11 @@ - + + true + + true The.Explicit.Name.Of.ResxResourceWithLogicalNameInSubDir From 0727149f5c865cbe24aa2d728a2b66f95ab4c6e2 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 18 Sep 2017 15:02:37 -0700 Subject: [PATCH 03/16] generate source for embedded resources in FSharp.Editor --- .../ClassificationDefinitions.fs | 10 +-- ...eywordToDisposableConstructorInvocation.fs | 2 +- .../ImplementInterfaceCodeFixProvider.fs | 4 +- .../MissingReferenceCodeFixProvider.fs | 4 +- .../CodeFix/RemoveUnusedOpens.fs | 2 +- .../CodeFix/RenameUnusedValue.fs | 6 +- .../src/FSharp.Editor/CodeFix/SimplifyName.fs | 4 +- .../SimplifyNameDiagnosticAnalyzer.fs | 4 +- .../Diagnostics/UnusedDeclarationsAnalyzer.fs | 4 +- .../UnusedOpensDiagnosticAnalyzer.fs | 4 +- .../DocComments/XMLDocumentation.fs | 4 +- .../FSharp.Editor/FSharp.Editor.Attributes.fs | 33 ++++++++ .../src/FSharp.Editor/FSharp.Editor.fsproj | 5 +- .../Navigation/GoToDefinitionService.fs | 14 ++-- .../src/FSharp.Editor/srFSharp.Editor.fs | 75 ------------------- 15 files changed, 67 insertions(+), 108 deletions(-) create mode 100644 vsintegration/src/FSharp.Editor/FSharp.Editor.Attributes.fs delete mode 100644 vsintegration/src/FSharp.Editor/srFSharp.Editor.fs diff --git a/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs b/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs index 38c6eacc768..806c54b0b35 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ClassificationDefinitions.fs @@ -140,7 +140,7 @@ module internal ClassificationDefinitions = type internal FSharpFunctionTypeFormat() as self = inherit ClassificationFormatDefinition() - do self.DisplayName <- SR.FSharpFunctionsOrMethodsClassificationType.Value + do self.DisplayName <- SR.FSharpFunctionsOrMethodsClassificationType() [)>] [] @@ -150,7 +150,7 @@ module internal ClassificationDefinitions = type internal FSharpMutableVarTypeFormat [](theme: ThemeColors) as self = inherit ClassificationFormatDefinition() - do self.DisplayName <- SR.FSharpMutableVarsClassificationType.Value + do self.DisplayName <- SR.FSharpMutableVarsClassificationType() self.ForegroundColor <- theme.GetColor FSharpClassificationTypes.MutableVar [)>] @@ -161,7 +161,7 @@ module internal ClassificationDefinitions = type internal FSharpPrintfTypeFormat [](theme: ThemeColors) as self = inherit ClassificationFormatDefinition() - do self.DisplayName <- SR.FSharpPrintfFormatClassificationType.Value + do self.DisplayName <- SR.FSharpPrintfFormatClassificationType() self.ForegroundColor <- theme.GetColor FSharpClassificationTypes.Printf [)>] @@ -172,7 +172,7 @@ module internal ClassificationDefinitions = type internal FSharpPropertyFormat() as self = inherit ClassificationFormatDefinition() - do self.DisplayName <- SR.FSharpPropertiesClassificationType.Value + do self.DisplayName <- SR.FSharpPropertiesClassificationType() [)>] [] @@ -182,5 +182,5 @@ module internal ClassificationDefinitions = type internal FSharpDisposableFormat [](theme: ThemeColors) as self = inherit ClassificationFormatDefinition() - do self.DisplayName <- SR.FSharpDisposablesClassificationType.Value + do self.DisplayName <- SR.FSharpDisposablesClassificationType() self.ForegroundColor <- theme.GetColor FSharpClassificationTypes.Disposable \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/CodeFix/AddNewKeywordToDisposableConstructorInvocation.fs b/vsintegration/src/FSharp.Editor/CodeFix/AddNewKeywordToDisposableConstructorInvocation.fs index ac295302dc5..0253a220ae7 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/AddNewKeywordToDisposableConstructorInvocation.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/AddNewKeywordToDisposableConstructorInvocation.fs @@ -19,7 +19,7 @@ type internal FSharpAddNewKeywordCodeFixProvider() = override this.RegisterCodeFixesAsync context : Task = async { - let title = SR.AddNewKeyword.Value + let title = SR.AddNewKeyword() context.RegisterCodeFix( CodeAction.Create( title, diff --git a/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs index 494f071ad56..a37be23a58e 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/ImplementInterfaceCodeFixProvider.fs @@ -130,8 +130,8 @@ type internal FSharpImplementInterfaceCodeFixProvider title) context.RegisterCodeFix(codeAction, diagnostics) - registerCodeFix SR.ImplementInterface.Value true - registerCodeFix SR.ImplementInterfaceWithoutTypeAnnotation.Value false + registerCodeFix (SR.ImplementInterface()) true + registerCodeFix (SR.ImplementInterfaceWithoutTypeAnnotation()) false else () diff --git a/vsintegration/src/FSharp.Editor/CodeFix/MissingReferenceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFix/MissingReferenceCodeFixProvider.fs index efa9e2f14da..91bfc716b15 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/MissingReferenceCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/MissingReferenceCodeFixProvider.fs @@ -71,7 +71,7 @@ type internal MissingReferenceCodeFixProvider() = | Some refProject -> let codefix = createCodeFix( - String.Format(SR.AddProjectReference.Value, refProject.Name), + String.Format(SR.AddProjectReference(), refProject.Name), context, AddProjectRef (ProjectReference refProject.Id) ) @@ -90,7 +90,7 @@ type internal MissingReferenceCodeFixProvider() = | Some metadataRef -> let codefix = createCodeFix( - String.Format(SR.AddAssemblyReference.Value, assemblyName), + String.Format(SR.AddAssemblyReference(), assemblyName), context, AddMetadataRef metadataRef ) diff --git a/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs b/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs index 1bbab71834d..fc6c71fb3a9 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/RemoveUnusedOpens.fs @@ -52,7 +52,7 @@ type internal FSharpRemoveUnusedOpensCodeFixProvider override __.RegisterCodeFixesAsync context : Task = async { let diagnostics = context.Diagnostics |> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id) |> Seq.toImmutableArray - context.RegisterCodeFix(createCodeFix(SR.RemoveUnusedOpens.Value, context), diagnostics) + context.RegisterCodeFix(createCodeFix(SR.RemoveUnusedOpens(), context), diagnostics) } |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) override __.GetFixAllProvider() = WellKnownFixAllProviders.BatchFixer diff --git a/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs b/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs index 3cb96a95e14..7b544ca866a 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs @@ -65,12 +65,12 @@ type internal FSharpRenameUnusedValueCodeFixProvider match symbolUse.Symbol with | :? FSharpMemberOrFunctionOrValue as func -> - createCodeFix(context, symbolName, SR.PrefixValueNameWithUnderscore.Value, TextChange(TextSpan(context.Span.Start, 0), "_")) + createCodeFix(context, symbolName, SR.PrefixValueNameWithUnderscore(), TextChange(TextSpan(context.Span.Start, 0), "_")) if func.IsMemberThisValue then - createCodeFix(context, symbolName, SR.RenameValueToDoubleUnderscore.Value, TextChange(context.Span, "__")) + createCodeFix(context, symbolName, SR.RenameValueToDoubleUnderscore(), TextChange(context.Span, "__")) elif not func.IsMember then - createCodeFix(context, symbolName, SR.RenameValueToUnderscore.Value, TextChange(context.Span, "_")) + createCodeFix(context, symbolName, SR.RenameValueToUnderscore(), TextChange(context.Span, "_")) | _ -> () } |> Async.Ignore diff --git a/vsintegration/src/FSharp.Editor/CodeFix/SimplifyName.fs b/vsintegration/src/FSharp.Editor/CodeFix/SimplifyName.fs index 2b727c8fc28..152cce06829 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/SimplifyName.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/SimplifyName.fs @@ -24,8 +24,8 @@ type internal FSharpSimplifyNameCodeFixProvider() = for diagnostic in context.Diagnostics |> Seq.filter (fun x -> x.Id = fixableDiagnosticId) do let title = match diagnostic.Properties.TryGetValue(SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey) with - | true, longIdent -> sprintf "%s '%s'" SR.SimplifyName.Value longIdent - | _ -> SR.SimplifyName.Value + | true, longIdent -> sprintf "%s '%s'" (SR.SimplifyName()) longIdent + | _ -> SR.SimplifyName() let codefix = createTextChangeCodeFix(title, context, (fun () -> asyncMaybe.Return [| TextChange(context.Span, "") |])) diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs index 0686c7ddd86..225a32d29e7 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs @@ -34,8 +34,8 @@ type internal SimplifyNameDiagnosticAnalyzer() = static let Descriptor = DiagnosticDescriptor( id = IDEDiagnosticIds.SimplifyNamesDiagnosticId, - title = SR.SimplifyName.Value, - messageFormat = SR.NameCanBeSimplified.Value, + title = SR.SimplifyName(), + messageFormat = SR.NameCanBeSimplified(), category = DiagnosticCategory.Style, defaultSeverity = DiagnosticSeverity.Hidden, isEnabledByDefault = true, diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs index b1868f9f5f1..a0466dd4ff4 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs @@ -24,8 +24,8 @@ type internal UnusedDeclarationsAnalyzer() = let Descriptor = DiagnosticDescriptor( id = DescriptorId, - title = SR.TheValueIsUnused.Value, - messageFormat = SR.TheValueIsUnused.Value, + title = SR.TheValueIsUnused(), + messageFormat = SR.TheValueIsUnused(), category = DiagnosticCategory.Style, defaultSeverity = DiagnosticSeverity.Hidden, isEnabledByDefault = true, diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs index 53c5d51b3d3..58226fb8f1e 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs @@ -150,8 +150,8 @@ type internal UnusedOpensDiagnosticAnalyzer() = static let Descriptor = DiagnosticDescriptor( id = IDEDiagnosticIds.RemoveUnnecessaryImportsDiagnosticId, - title = SR.RemoveUnusedOpens.Value, - messageFormat = SR.UnusedOpens.Value, + title = SR.RemoveUnusedOpens(), + messageFormat = SR.UnusedOpens(), category = DiagnosticCategory.Style, defaultSeverity = DiagnosticSeverity.Hidden, isEnabledByDefault = true, diff --git a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs index 435152abd5c..db616ba5103 100644 --- a/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs +++ b/vsintegration/src/FSharp.Editor/DocComments/XMLDocumentation.fs @@ -198,7 +198,7 @@ module internal XmlDocumentation = if not started then started <- true AppendHardLine collector - AppendOnNewLine collector SR.ExceptionsLabel.Value + AppendOnNewLine collector (SR.ExceptionsHeader()) EnsureHardLine collector collector.Add(tagSpace " ") WriteTypeName collector exnType.Value @@ -349,7 +349,7 @@ module internal XmlDocumentation = let ProcessGenericParameters (tps: Layout list) = if not tps.IsEmpty then AppendHardLine typeParameterMapCollector - AppendOnNewLine typeParameterMapCollector SR.GenericParametersLabel.Value + AppendOnNewLine typeParameterMapCollector (SR.GenericParametersHeader()) for tp in tps do AppendHardLine typeParameterMapCollector typeParameterMapCollector.Add(tagSpace " ") diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.Attributes.fs b/vsintegration/src/FSharp.Editor/FSharp.Editor.Attributes.fs new file mode 100644 index 00000000000..0852f72ab41 --- /dev/null +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.Attributes.fs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +//-------------------------------------------------------------------------------------- +// Attributes used to mark up editable properties + +[] +type internal SRDescriptionAttribute(description:string) = + inherit DescriptionAttribute(description) + let mutable replaced = false + + override x.Description = + if not (replaced) then + replaced <- true + x.DescriptionValue <- SR.GetString(base.Description) + base.Description + +[] +type internal SRCategoryAttribute(category:string) = + inherit CategoryAttribute(category) + override x.GetLocalizedString(value:string) = SR.GetString(value) + +[] +type internal SRDisplayNameAttribute(name:string) = + inherit DisplayNameAttribute() + + override x.DisplayName = + match SR.GetString(name) with + | null -> + Debug.Assert(false, "String resource '" + name + "' is missing") + name + | result -> result diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index ae38f48257e..a6403bcfaa4 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -29,8 +29,9 @@ true - - + + Microsoft.VisualStudio.FSharp.Editor.SR + diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs index 9b7b12aecd6..9925058fcfd 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs @@ -252,7 +252,7 @@ type internal FSharpGoToDefinitionService match navigableItem with | Some navigableItem -> - statusBar.Message SR.NavigatingTo.Value + statusBar.Message (SR.NavigatingTo()) let workspace = navigableItem.Document.Project.Solution.Workspace let navigationService = workspace.Services.GetService() @@ -263,11 +263,11 @@ type internal FSharpGoToDefinitionService if result then statusBar.Clear() else - statusBar.TempMessage SR.CannotNavigateUnknown.Value + statusBar.TempMessage (SR.CannotNavigateUnknown()) result | None -> - statusBar.TempMessage SR.CannotDetermineSymbol.Value + statusBar.TempMessage (SR.CannotDetermineSymbol()) true /// Navigate to the positon of the textSpan in the provided document @@ -280,7 +280,7 @@ type internal FSharpGoToDefinitionService if navigationService.TryNavigateToSpan (workspace, navigableItem.Document.Id, navigableItem.SourceSpan, options) then true else - statusBar.TempMessage SR.CannotNavigateUnknown.Value + statusBar.TempMessage (SR.CannotNavigateUnknown()) false /// find the declaration location (signature file/.fsi) of the target symbol if possible, fall back to definition @@ -405,7 +405,7 @@ type internal FSharpGoToDefinitionService member this.TryGoToDefinition(document: Document, position: int, cancellationToken: CancellationToken) = let definitionTask = this.FindDefinitionsTask (document, position, cancellationToken) - statusBar.Message SR.LocatingSymbol.Value + statusBar.Message (SR.LocatingSymbol()) use __ = statusBar.Animate() // Wrap this in a try/with as if the user clicks "Cancel" on the thread dialog, we'll be cancelled @@ -419,7 +419,7 @@ type internal FSharpGoToDefinitionService match completionError with | Some message -> - statusBar.TempMessage <| String.Format(SR.NavigateToFailed.Value, message) + statusBar.TempMessage <| String.Format(SR.NavigateToFailed(), message) // Don't show the dialog box as it's most likely that the user cancelled. // Don't make them click twice. @@ -439,5 +439,5 @@ type internal FSharpGoToDefinitionService // presenter.DisplayResult(navigableItem.DisplayString, definitionTask.Result) //true else - statusBar.TempMessage SR.CannotDetermineSymbol.Value + statusBar.TempMessage (SR.CannotDetermineSymbol()) false \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/srFSharp.Editor.fs b/vsintegration/src/FSharp.Editor/srFSharp.Editor.fs deleted file mode 100644 index e2e64e3d694..00000000000 --- a/vsintegration/src/FSharp.Editor/srFSharp.Editor.fs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -namespace Microsoft.VisualStudio.FSharp.Editor - -open System -open System.ComponentModel -open System.Diagnostics - -[] -module SR = - let private resources = lazy (new System.Resources.ResourceManager("FSharp.Editor", System.Reflection.Assembly.GetExecutingAssembly())) - - let GetString(name:string) = - let s = resources.Value.GetString(name, System.Globalization.CultureInfo.CurrentUICulture) -#if DEBUG - if null = s then System.Diagnostics.Debug.Assert(false, sprintf "**RESOURCE ERROR**: Resource token %s does not exist!" name) -#endif - s.Replace(@"\n", System.Environment.NewLine) - - // Sigh!!!! We do this because at the moment we don't have a tool to generate the SR from a resx file - let AddNewKeyword = lazy ( GetString "AddNewKeyword" ) // "Add 'new' keyword" - let PrefixValueNameWithUnderscore = lazy ( GetString "PrefixValueNameWithUnderscore" ) // "Prefix value name with underscore" - let RenameValueToUnderscore = lazy ( GetString "RenameValueToUnderscore" ) // "Rename value to '_'" - let RenameValueToDoubleUnderscore = lazy ( GetString "RenameValueToDoubleUnderscore" ) // "Rename value to '__'" - let ImplementInterface = lazy ( GetString "ImplementInterface" ) - let ImplementInterfaceWithoutTypeAnnotation = lazy ( GetString "ImplementInterfaceWithoutTypeAnnotation" ) - let SimplifyName = lazy ( GetString "SimplifyName") - let NameCanBeSimplified = lazy ( GetString "NameCanBeSimplified") - let FSharpFunctionsOrMethodsClassificationType = lazy (GetString "FSharpFunctionsOrMethodsClassificationType") - let FSharpMutableVarsClassificationType = lazy (GetString "FSharpMutableVarsClassificationType") - let FSharpPrintfFormatClassificationType = lazy (GetString "FSharpPrintfFormatClassificationType") - let FSharpPropertiesClassificationType = lazy (GetString "FSharpPropertiesClassificationType") - let FSharpDisposablesClassificationType = lazy (GetString "FSharpDisposablesClassificationType") - let TheValueIsUnused = lazy (GetString "TheValueIsUnused") - let RemoveUnusedOpens = lazy (GetString "RemoveUnusedOpens") - let UnusedOpens = lazy (GetString "UnusedOpens") - let AddProjectReference = lazy (GetString "AddProjectReference") - let AddAssemblyReference = lazy (GetString "AddAssemblyReference") - let NavigatingTo = lazy (GetString "NavigatingTo") - let CannotDetermineSymbol = lazy (GetString "CannotDetermineSymbol") - let CannotNavigateUnknown = lazy (GetString "CannotNavigateUnknown") - let LocatingSymbol = lazy (GetString "LocatingSymbol") - let NavigateToFailed = lazy (GetString "NavigateToFailed") - let ExceptionsLabel = lazy (GetString "ExceptionsHeader") - let GenericParametersLabel = lazy (GetString "GenericParametersHeader") - - //-------------------------------------------------------------------------------------- - // Attributes used to mark up editable properties - - [] - type internal SRDescriptionAttribute(description:string) = - inherit DescriptionAttribute(description) - let mutable replaced = false - - override x.Description = - if not (replaced) then - replaced <- true - x.DescriptionValue <- GetString(base.Description) - base.Description - - [] - type internal SRCategoryAttribute(category:string) = - inherit CategoryAttribute(category) - override x.GetLocalizedString(value:string) = - GetString(value) - - [] - type internal SRDisplayNameAttribute(name:string) = - inherit DisplayNameAttribute() - - override x.DisplayName = - match GetString(name) with - | null -> - Debug.Assert(false, "String resource '" + name + "' is missing") - name - | result -> result From 1ce305b1619f7fe4cebef6e6039dda3286a1280a Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 18 Sep 2017 15:29:04 -0700 Subject: [PATCH 04/16] generate source for embedded resources in FSharp.LanguageService --- .../src/FSharp.LanguageService/Error.fs | 28 ------------------- .../FSharp.LanguageService.fsproj | 4 ++- .../FSharp.LanguageService/FSharpSource.fs | 2 +- .../FSharp.LanguageService/GotoDefinition.fs | 16 +++++------ 4 files changed, 12 insertions(+), 38 deletions(-) diff --git a/vsintegration/src/FSharp.LanguageService/Error.fs b/vsintegration/src/FSharp.LanguageService/Error.fs index e370dbcb426..e2a785a686a 100644 --- a/vsintegration/src/FSharp.LanguageService/Error.fs +++ b/vsintegration/src/FSharp.LanguageService/Error.fs @@ -23,36 +23,8 @@ module internal Error = let UseOfUnitializedServiceProvider = invalidOperation "ServiceProvider used before complete initialization." let Bug = invalidOperation "Unexpected." -/// Localizable strings. -module internal Strings = - - let private resources = new System.Resources.ResourceManager("FSLangSvcStrings", System.Reflection.Assembly.GetExecutingAssembly()) - - /// Exceptions: - let ExceptionsHeader = resources.GetString("ExceptionsHeader", System.Globalization.CultureInfo.CurrentUICulture) - /// (still building content cache) - let StillBuildingContentCache = resources.GetString("StillBuildingContentCache", System.Globalization.CultureInfo.CurrentUICulture) - - let GetString(s) = resources.GetString(s, System.Globalization.CultureInfo.CurrentUICulture) - - module Errors = - let private Format1 id (s : string) = - let format = GetString(id) - System.String.Format(format, s) - - let GotoDefinitionFailed () = GetString "GotoDefinitionFailed_Generic" - let GotoDefinitionFailed_ProvidedType(typeName : string) = Format1 "GotoDefinitionFailed_ProvidedType" typeName - let GotoFailed_ProvidedMember(name : string) = Format1 "GotoDefinitionFailed_ProvidedMember" name - let GotoDefinitionFailed_NotIdentifier () = GetString "GotoDefinitionFailed_NotIdentifier" - let GotoDefinitionFailed_NoTypecheckInfo () = GetString "GotoDefinitionFailed_NoTypecheckInfo" - let GotoDefinitionFailed_NoSourceCode () = GetString "GotoDefinitionFailed_NotSourceCode" - /// Assert helpers type internal Assert() = /// Display a good exception for this error message and then rethrow. static member Exception(e:Exception) = System.Diagnostics.Debug.Assert(false, "Unexpected exception seen in language service", e.ToString()) - - - - diff --git a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj index 11af261860c..28e76eebe57 100644 --- a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj +++ b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj @@ -50,7 +50,9 @@ false - + + Microsoft.VisualStudio.FSharp.LanguageService.Strings + diff --git a/vsintegration/src/FSharp.LanguageService/FSharpSource.fs b/vsintegration/src/FSharp.LanguageService/FSharpSource.fs index cba2beaad66..f24edf88fc8 100644 --- a/vsintegration/src/FSharp.LanguageService/FSharpSource.fs +++ b/vsintegration/src/FSharp.LanguageService/FSharpSource.fs @@ -293,7 +293,7 @@ type internal FSharpIntelliSenseToAppearAdornment_DEPRECATED(view: IWpfTextView, else new SnapshotSpan(view.TextSnapshot, Span.FromBounds(i-1, i)) let g = textViewLines.GetMarkerGeometry(span) - let tb = new System.Windows.Controls.TextBlock(Text=Strings.GetString "IntelliSenseLoading", FontFamily=System.Windows.Media.FontFamily(fontFamily), FontSize=pointSize) + let tb = new System.Windows.Controls.TextBlock(Text=Strings.IntelliSenseLoading(), FontFamily=System.Windows.Media.FontFamily(fontFamily), FontSize=pointSize) tb.Foreground <- excludedCodeForegroundColorBrush let sp = new System.Windows.Controls.StackPanel(Orientation=System.Windows.Controls.Orientation.Horizontal) System.Windows.Documents.TextElement.SetForeground(sp, excludedCodeForegroundColorBrush.GetAsFrozen() :?> System.Windows.Media.Brush) diff --git a/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs b/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs index c06350adb0a..dd4f2df45be 100644 --- a/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs +++ b/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs @@ -65,12 +65,12 @@ module internal GotoDefinition = Some(colIdent, tag, qualId), false match identInfo with | None -> - Strings.Errors.GotoDefinitionFailed_NotIdentifier () + Strings.GotoDefinitionFailed_NotIdentifier() |> GotoDefinitionResult_DEPRECATED.MakeError | Some(colIdent, tag, qualId) -> if typedResults.HasFullTypeCheckInfo then if Parser.tokenTagToTokenId tag <> Parser.TOKEN_IDENT then - Strings.Errors.GotoDefinitionFailed_NotIdentifier () + Strings.GotoDefinitionFailed_NotIdentifier() |> GotoDefinitionResult_DEPRECATED.MakeError else match typedResults.GetDeclarationLocation (line+1, colIdent, lineStr, qualId, false) |> Async.RunSynchronously with @@ -83,16 +83,16 @@ module internal GotoDefinition = Trace.Write("LanguageService", sprintf "Goto definition failed: Reason %+A" reason) let text = match reason with - | FSharpFindDeclFailureReason.Unknown _message -> Strings.Errors.GotoDefinitionFailed() - | FSharpFindDeclFailureReason.NoSourceCode -> Strings.Errors.GotoDefinitionFailed_NoSourceCode() - | FSharpFindDeclFailureReason.ProvidedType(typeName) -> Strings.Errors.GotoDefinitionFailed_ProvidedType(typeName) - | FSharpFindDeclFailureReason.ProvidedMember(name) -> Strings.Errors.GotoFailed_ProvidedMember(name) + | FSharpFindDeclFailureReason.Unknown _message -> Strings.GotoDefinitionFailed_Generic() + | FSharpFindDeclFailureReason.NoSourceCode -> Strings.GotoDefinitionFailed_NotSourceCode() + | FSharpFindDeclFailureReason.ProvidedType(typeName) -> String.Format(Strings.GotoDefinitionFailed_ProvidedType(), typeName) + | FSharpFindDeclFailureReason.ProvidedMember(name) -> String.Format(Strings.GotoDefinitionFailed_ProvidedMember(), name) GotoDefinitionResult_DEPRECATED.MakeError text | FSharpFindDeclResult.ExternalDecl _ -> - GotoDefinitionResult_DEPRECATED.MakeError(Strings.Errors.GotoDefinitionFailed_NoSourceCode()) + GotoDefinitionResult_DEPRECATED.MakeError(Strings.GotoDefinitionFailed_NotSourceCode()) else Trace.Write("LanguageService", "Goto definition: No 'TypeCheckInfo' available") - Strings.Errors.GotoDefinitionFailed_NoTypecheckInfo() + Strings.GotoDefinitionFailed_NoTypecheckInfo() |> GotoDefinitionResult_DEPRECATED.MakeError gotoDefinition false From e26198f89cc09872651440d9c3917d295320b9bb Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 18 Sep 2017 16:39:30 -0700 Subject: [PATCH 05/16] generate source for embedded resources in FSharp.ProjectSystem.FSharp --- .../FSharp.Build/FSharpEmbedResXSource.fs | 19 ++- .../Vsix/RegisterFsharpPackage.pkgdef | 2 +- .../MSBuildUtilities.fs | 2 +- .../FSharp.ProjectSystem.FSharp/Project.fs | 40 +++--- .../ProjectPrelude.fs | 128 ------------------ .../ProjectSystem.fsproj | 3 +- .../VSPackage.resx | 2 +- 7 files changed, 38 insertions(+), 158 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index 790a296d495..08139ebe179 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -29,7 +29,8 @@ module internal {1} = type private C (_dummy:System.Object) = class end let mutable Culture = System.Globalization.CultureInfo.CurrentUICulture let ResourceManager = new System.Resources.ResourceManager(""{2}"", C(null).GetType().GetTypeInfo().Assembly) - let GetString(name:System.String) : System.String = ResourceManager.GetString(name, Culture)" + let GetString(name:System.String) : System.String = ResourceManager.GetString(name, Culture) + let GetObject(name:System.String) : System.Object = ResourceManager.GetObject(name, Culture)" let generateSource (resx:string) (fullModuleName:string) (generateLegacy:bool) = try @@ -43,24 +44,30 @@ module internal {1} = let sourcePath = Path.Combine(_outputPath, justFileName + ".fs") printMessage <| sprintf "Generating: %s" sourcePath let body = - XDocument.Load(resx).Descendants(XName.op_Implicit "data") + let xname = XName.op_Implicit + XDocument.Load(resx).Descendants(xname "data") |> Seq.fold (fun (sb:StringBuilder) (node:XElement) -> let name = - match node.Attribute(XName.op_Implicit "name") with + match node.Attribute(xname "name") with | null -> failwith "Missing resource name" | attr -> attr.Value let docComment = - match node.Elements(XName.op_Implicit "value").FirstOrDefault() with + match node.Elements(xname "value").FirstOrDefault() with | null -> failwith <| sprintf "Missing resource value for '%s'" name | element -> element.Value.Trim() let identifier = if Char.IsLetter(name.[0]) || name.[0] = '_' then name else "_" + name let commentBody = - XElement(XName.op_Implicit "summary", docComment).ToString().Split([|"\r\n"; "\r"; "\n"|], StringSplitOptions.None) + XElement(xname "summary", docComment).ToString().Split([|"\r\n"; "\r"; "\n"|], StringSplitOptions.None) |> Array.fold (fun (sb:StringBuilder) line -> sb.AppendLine(" /// " + line)) (StringBuilder()) // add the resource let accessorBody = if generateLegacy then sprintf " let %s = \"%s\"" identifier name - else sprintf " let %s() = GetString(\"%s\")" identifier name + else + let accessorFunction = match node.Attribute(xname "type") with + | null -> "GetString" + | _ -> "GetObject" + // TODO: When calling the `GetObject` version, parse the `type` attribute to discover the proper return type + sprintf " let %s() = %s(\"%s\")" identifier accessorFunction name sb.AppendLine().Append(commentBody).AppendLine(accessorBody) ) sb File.WriteAllText(sourcePath, body.ToString()) diff --git a/vsintegration/Vsix/RegisterFsharpPackage.pkgdef b/vsintegration/Vsix/RegisterFsharpPackage.pkgdef index 156ece7c238..ec8375a91b5 100644 --- a/vsintegration/Vsix/RegisterFsharpPackage.pkgdef +++ b/vsintegration/Vsix/RegisterFsharpPackage.pkgdef @@ -58,7 +58,7 @@ "CompanyName"="Microsoft Corp." [$RootKey$\Menus] -"{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}"=", 1000.ctmenu, 1" +"{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}"=", 1000_ctmenu, 1" [$RootKey$\CLSID\{e1194663-db3c-49eb-8b45-276fcdc440ea}] "InprocServer32"="$WinDir$\SYSTEM32\MSCOREE.DLL" diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/MSBuildUtilities.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/MSBuildUtilities.fs index 7d3fc17e32a..1a639984f99 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/MSBuildUtilities.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/MSBuildUtilities.fs @@ -125,7 +125,7 @@ type internal MSBuildUtilities() = Inc(curPathParts) curPathParts.Add(pathParts.[curPathParts.Count]) // e.g. transition from A\ to A\D\E\bar.fs if not(alreadyRenderedFolders.Add(new List(curPathParts))) && throwIfCannotRender then - raise <| new InvalidOperationException(String.Format(FSharpSR.GetString(FSharpSR.ProjectRenderFolderMultiple), projectNode.ProjectFile, bi.Include)) + raise <| new InvalidOperationException(String.Format(FSharpSR.ProjectRenderFolderMultiple(), projectNode.ProjectFile, bi.Include)) Inc(curPathParts) if bi.ItemType = ProjectFileConstants.Folder then explicitFolders.Add(new List<_>(pathParts), (bi,0)) diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index f78462de440..5ce8b6668f0 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -519,7 +519,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem VsShellUtilities.ShowMessageBox ( serviceProvider = this.Site, - message = FSharpSR.GetString(FSharpSR.FSharpCoreVersionIsNotLegacyCompatible), + message = FSharpSR.FSharpCoreVersionIsNotLegacyCompatible(), title = null, icon = OLEMSGICON.OLEMSGICON_QUERY, msgButton = OLEMSGBUTTON.OLEMSGBUTTON_YESNO, @@ -835,7 +835,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem /// Full path to destination file override x.AddFileFromTemplate(source:string, target:string ) = if not (Microsoft.FSharp.Compiler.AbstractIL.Internal.Library.Shim.FileSystem.SafeExists(source)) then - raise <| new FileNotFoundException(String.Format(FSharpSR.GetString(FSharpSR.TemplateNotFound), source)) + raise <| new FileNotFoundException(String.Format(FSharpSR.TemplateNotFound(), source)) // We assume that there is no token inside the file because the only // way to add a new element should be through the template wizard that @@ -940,7 +940,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem /// The formatlist to return override x.GetFormatList(formatlist:byref ) = // see docs for IPersistFileFormat.GetFormatList for correct format of this string - formatlist <- sprintf "%s\n*.fsproj\n" (FSharpSR.GetString(FSharpSR.ProjectFileExtensionFilter)) + formatlist <- sprintf "%s\n*.fsproj\n" (FSharpSR.ProjectFileExtensionFilter()) VSConstants.S_OK member this.IsCurrentProjectDotNetPortable() = this.CheckProjectFrameworkIdentifier(".NETPortable") @@ -986,7 +986,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem stripEndingSemicolon paths let dialogTitle = - let text = FSharpSR.GetString(FSharpSR.AddReferenceDialogTitleDev11) + let text = FSharpSR.AddReferenceDialogTitle_Dev11() String.Format(text, self.VSProject.Project.Name) let referenceContainerNode = this.GetReferenceContainer() :?> ReferenceContainerNode @@ -1022,9 +1022,9 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem // MSDN: Gets or sets whether the assembly is referenced implicitly assemblyReferenceProviderContext.IsImplicitlyReferenced <- false // MSDN: Gets or sets the message to display during retargeting. - assemblyReferenceProviderContext.RetargetingMessage <- FSharpSR.GetString(FSharpSR.AddReferenceAssemblyPageDialogRetargetingText) + assemblyReferenceProviderContext.RetargetingMessage <- FSharpSR.AddReferenceAssemblyPageDialogRetargetingText() // MSDN: Sets the custom no items message for the specified tab. - assemblyReferenceProviderContext.SetNoItemsMessageForTab(uint32 __VSASSEMBLYPROVIDERTAB.TAB_ASSEMBLY_FRAMEWORK, FSharpSR.GetString(FSharpSR.AddReferenceAssemblyPageDialogNoItemsText)) + assemblyReferenceProviderContext.SetNoItemsMessageForTab(uint32 __VSASSEMBLYPROVIDERTAB.TAB_ASSEMBLY_FRAMEWORK, FSharpSR.AddReferenceAssemblyPageDialogNoItemsText()) // we support only fixed set of portable profiles thus retargeting is prohibited assemblyReferenceProviderContext.SupportsRetargeting <- false @@ -1079,7 +1079,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem let c = let c = componentDialog.CreateProviderContext(VSConstants.FileReferenceProvider_Guid) let fileReferenceProviderContext = c :?> IVsFileReferenceProviderContext - fileReferenceProviderContext.BrowseFilter <- sprintf "%s|*.dll;*.exe;" (FSharpSR.GetString FSharpSR.ComponentFileExtensionFilter) + fileReferenceProviderContext.BrowseFilter <- sprintf "%s|*.dll;*.exe;" (FSharpSR.ComponentFileExtensionFilter()) c yield c // TODO, eventually, win8 stuff @@ -1329,8 +1329,8 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem use sourcesAndFlagsWaitDialog = { - WaitCaption = FSharpSR.GetString FSharpSR.ProductName - WaitMessage = FSharpSR.GetString FSharpSR.ComputingSourcesAndFlags + WaitCaption = FSharpSR.ProductName() + WaitMessage = FSharpSR.ComputingSourcesAndFlags() ProgressText = Some x.ProjectFile StatusBmpAnim = null StatusBarText = None @@ -1769,8 +1769,8 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem if waitCount = 0 then waitDialog <- { - WaitCaption = FSharpSR.GetString FSharpSR.ProductName - WaitMessage = FSharpSR.GetString FSharpSR.UpdatingSolutionConfiguration + WaitCaption = FSharpSR.ProductName() + WaitMessage = FSharpSR.UpdatingSolutionConfiguration() ProgressText = None StatusBmpAnim = null StatusBarText = None @@ -1932,13 +1932,13 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem VsShellUtilities.ShowMessageBox ( node.Site, - FSharpSR.GetString(FSharpSR.Dev11SupportsOnlySilverlight5), + FSharpSR.Dev11SupportsOnlySilverlight5(), null, OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST ) |> ignore Marshal.ThrowExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED) let result = - VsShellUtilities.ShowMessageBox(node.Site, FSharpSR.GetStringWithCR(FSharpSR.NeedReloadToChangeTargetFx), + VsShellUtilities.ShowMessageBox(node.Site, FSharpSR.NeedReloadToChangeTargetFx().Replace("\n", Environment.NewLine), null, OLEMSGICON.OLEMSGICON_QUERY, OLEMSGBUTTON.OLEMSGBUTTON_YESNO, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST) if result <> NativeMethods.IDYES then @@ -1980,7 +1980,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem | OutputType.WinExe -> "WinExe" | OutputType.Exe -> "Exe" | OutputType.Library -> "Library" - | _ -> raise <| ArgumentException(FSharpSR.GetString(FSharpSR.InvalidOutputType), "value") + | _ -> raise <| ArgumentException(FSharpSR.InvalidOutputType(), "value") this.Node.ProjectMgr.SetProjectProperty(ProjectFileConstants.OutputType, outputTypeInteger) [] @@ -2013,7 +2013,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem | 0 -> "Always" | 1 -> "OnBuildSuccess" | 2 -> "OnOutputUpdated" - | _ -> raise <| ArgumentException(FSharpSR.GetString(FSharpSR.InvalidRunPostBuildEvent), "value") + | _ -> raise <| ArgumentException(FSharpSR.InvalidRunPostBuildEvent(), "value") this.Node.ProjectMgr.SetProjectProperty(ProjectFileConstants.RunPostBuildEvent, runPostBuildEventInteger) type internal FSharpFolderNode(root : FSharpProjectNode, relativePath : string, projectElement : ProjectElement) = @@ -2425,11 +2425,11 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem if fileChildren = [nodeToBeMoved] then Ok siblingNode else - Error <| String.Format(FSharpSR.GetString(FSharpSR.FileCannotBePlacedMultipleFiles), siblingNode.VirtualNodeName) + Error <| String.Format(FSharpSR.FileCannotBePlacedMultipleFiles(), siblingNode.VirtualNodeName) | Some siblingNode -> Ok siblingNode | None -> - Error <| FSharpSR.GetString(FSharpSR.FileCannotBePlacedDifferentSubtree) + Error <| FSharpSR.FileCannotBePlacedDifferentSubtree() |> function | Ok node -> unlinkFromSiblings node @@ -2464,9 +2464,9 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem let bodyString = match location with - | Above -> FSharpSR.FileCannotBePlacedBodyAbove - | Below -> FSharpSR.FileCannotBePlacedBodyBelow - |> FSharpSR.GetStringWithCR + | Above -> FSharpSR.FileCannotBePlacedBodyAbove() + | Below -> FSharpSR.FileCannotBePlacedBodyBelow() + |> (fun s -> s.Replace("\n", Environment.NewLine)) let entireMessage = String.Format(bodyString, relPath, relTargetPath, message) VsShellUtilities.ShowMessageBox(root.Site, title, entireMessage, icon, buttons, defaultButton) |> ignore diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectPrelude.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectPrelude.fs index ce8d742998e..fdc9282c053 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectPrelude.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectPrelude.fs @@ -121,134 +121,6 @@ namespace Microsoft.VisualStudio.FSharp.ProjectSystem open Helpers - //-------------------------------------------------------------------------------------- - // The Resource Reader - - module internal FSharpSR = - [] - let ProjectReferenceError2 = "ProjectReferenceError2" - [] - let Application = "Application" - [] - let ApplicationIcon = "ApplicationIcon" - [] - let ApplicationIconDescription = "ApplicationIconDescription" - [] - let AssemblyName = "AssemblyName" - [] - let AssemblyNameDescription = "AssemblyNameDescription" - [] - let DefaultNamespace = "DefaultNamespace" - [] - let DefaultNamespaceDescription = "DefaultNamespaceDescription" - [] - let GeneralCaption = "GeneralCaption" - [] - let InvalidOutputType = "InvalidOutputType" - [] - let InvalidRunPostBuildEvent = "InvalidRunPostBuildEvent" - [] - let InvalidTargetFrameworkVersion = "InvalidTargetFrameworkVersion" - [] - let OutputFile = "OutputFile" - [] - let OutputFileDescription = "OutputFileDescription" - [] - let OutputType = "OutputType" - [] - let OutputTypeDescription = "OutputTypeDescription" - [] - let ProductName = "ProductName" - [] - let Project = "Project" - [] - let ProjectFile = "ProjectFile" - [] - let ProjectFileDescription = "ProjectFileDescription" - [] - let ProjectFileExtensionFilter = "ProjectFileExtensionFilter" - [] - let ComponentFileExtensionFilter = "ComponentFileExtensionFilter" - [] - let ProjectFolder = "ProjectFolder" - [] - let ProjectRenderFolderMultiple = "ProjectRenderFolderMultiple" - [] - let ProjectFolderDescription = "ProjectFolderDescription" - [] - let PropertyDefaultNamespace = "PropertyDefaultNamespace" - [] - let StartupObject = "StartupObject" - [] - let StartupObjectDescription = "StartupObjectDescription" - [] - let TargetPlatform = "TargetPlatform" - [] - let TargetPlatformDescription = "TargetPlatformDescription" - [] - let TargetPlatformLocation = "TargetPlatformLocation" - [] - let TargetPlatformLocationDescription = "TargetPlatformLocationDescription" - [] - let OtherFlags = "OtherFlags" - [] - let OtherFlagsDescription = "OtherFlagsDescription" - [] - let Tailcalls = "Tailcalls" - [] - let TailcallsDescription = "TailcallsDescription" - [] - let UseStandardResourceNames = "UseStandardResourceNames" - [] - let UseStandardResourceNamesDescription = "UseStandardResourceNamesDescription" - [] - let TemplateNotFound = "TemplateNotFound" - [] - let NeedReloadToChangeTargetFx = "NeedReloadToChangeTargetFx" - [] - let NeedReloadToChangeTargetFxCaption = "NeedReloadToChangeTargetFxCaption" - [] - let Build = "Build" - [] - let AddReferenceDialogTitle = "AddReferenceDialogTitle"; - [] - let AddReferenceDialogTitleDev11 = "AddReferenceDialogTitle_Dev11"; - [] - let Dev11SupportsOnlySilverlight5 = "Dev11SupportsOnlySilverlight5"; - [] - let AddReferenceAssemblyPageDialogRetargetingText = "AddReferenceAssemblyPageDialogRetargetingText"; - [] - let AddReferenceAssemblyPageDialogNoItemsText = "AddReferenceAssemblyPageDialogNoItemsText"; - [] - let FSharpCoreVersionIsNotLegacyCompatible = "FSharpCoreVersionIsNotLegacyCompatible"; - [] - let ComputingSourcesAndFlags = "ComputingSourcesAndFlags" - [] - let UpdatingSolutionConfiguration = "UpdatingSolutionConfiguration" - [] - let FileCannotBePlacedBodyAbove = "FileCannotBePlacedBodyAbove" - [] - let FileCannotBePlacedBodyBelow = "FileCannotBePlacedBodyBelow" - [] - let FileCannotBePlacedDifferentSubtree = "FileCannotBePlacedDifferentSubtree" - [] - let FileCannotBePlacedMultipleFiles = "FileCannotBePlacedMultipleFiles" - - type private TypeInThisAssembly = class end - let thisAssembly = typeof.Assembly - - let private resources = lazy (new System.Resources.ResourceManager("VSPackage", thisAssembly)) - - let GetString(name:string) = - resources.Force().GetString(name, CultureInfo.CurrentUICulture) - - let GetStringWithCR(name:string) = - let s = resources.Force().GetString(name, CultureInfo.CurrentUICulture) - s.Replace(@"\n", Environment.NewLine) - - let GetObject(name:string) = - resources.Force().GetObject(name, CultureInfo.CurrentUICulture) - //-------------------------------------------------------------------------------------- // Attributes used to mark up editable properties diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj index 119a1ef0a51..ad2abef6ce8 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj @@ -79,7 +79,8 @@ 210 - + + Microsoft.VisualStudio.FSharp.ProjectSystem.FSharpSR true diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx b/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx index f66f0049a8a..5bb05a0bfe1 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx @@ -221,7 +221,7 @@ Resources\FSharpAboutBox.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - + ctofiles\MenusAndCommands.cto;System.Byte[], mscorlib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a From 910569321fa94a892fdae796539df617e1a9d99f Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 19 Sep 2017 11:11:27 -0700 Subject: [PATCH 06/16] generate source for embedded resources in FSharp.VS.FSI --- .../FSharp.Build/FSharpEmbedResXSource.fs | 20 ++++--- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 1 + .../src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj | 5 +- .../FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs | 12 +++++ .../src/FSharp.VS.FSI/fsiLanguageService.fs | 25 ++++----- .../src/FSharp.VS.FSI/srProperties.fs | 52 ------------------- 6 files changed, 42 insertions(+), 73 deletions(-) create mode 100644 vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs delete mode 100644 vsintegration/src/FSharp.VS.FSI/srProperties.fs diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index 08139ebe179..f7a47ca56fa 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -32,7 +32,7 @@ module internal {1} = let GetString(name:System.String) : System.String = ResourceManager.GetString(name, Culture) let GetObject(name:System.String) : System.Object = ResourceManager.GetObject(name, Culture)" - let generateSource (resx:string) (fullModuleName:string) (generateLegacy:bool) = + let generateSource (resx:string) (fullModuleName:string) (generateLegacy:bool) (generateLiteral:bool) = try let printMessage = printfn "FSharpEmbedResXSource: %s" let justFileName = Path.GetFileNameWithoutExtension(resx) @@ -61,8 +61,10 @@ module internal {1} = |> Array.fold (fun (sb:StringBuilder) line -> sb.AppendLine(" /// " + line)) (StringBuilder()) // add the resource let accessorBody = - if generateLegacy then sprintf " let %s = \"%s\"" identifier name - else + match (generateLegacy, generateLiteral) with + | (true, true) -> sprintf " []\n let %s = \"%s\"" identifier name + | (true, false) -> sprintf " let %s = \"%s\"" identifier name // the [] attribute can't be used for FSharp.Core + | (false, _) -> let accessorFunction = match node.Attribute(xname "type") with | null -> "GetString" | _ -> "GetObject" @@ -99,17 +101,21 @@ module internal {1} = with get() = _hostObject and set(value) = _hostObject <- value member this.Execute() = - let getBooleanMetadata (metadataName:string) (item:ITaskItem) = String.Compare(item.GetMetadata(metadataName), "true", StringComparison.OrdinalIgnoreCase) = 0 + let getBooleanMetadata (metadataName:string) (defaultValue:bool) (item:ITaskItem) = + match item.GetMetadata(metadataName) with + | value when String.IsNullOrWhiteSpace(value) -> defaultValue + | value -> String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) = 0 let generatedFiles, generatedResult = this.EmbeddedResource - |> Array.filter (getBooleanMetadata "GenerateSource") + |> Array.filter (getBooleanMetadata "GenerateSource" false) |> Array.fold (fun (resultList, aggregateResult) item -> let moduleName = match item.GetMetadata("GeneratedModuleName") with | null -> Path.GetFileNameWithoutExtension(item.ItemSpec) | value -> value - let generateLegacy = getBooleanMetadata "GenerateLegacyCode" item - match generateSource item.ItemSpec moduleName generateLegacy with + let generateLegacy = getBooleanMetadata "GenerateLegacyCode" false item + let generateLiteral = getBooleanMetadata "GenerateLiterals" true item + match generateSource item.ItemSpec moduleName generateLegacy generateLiteral with | Some (source) -> ((source :: resultList), aggregateResult) | None -> (resultList, false) ) ([], true) diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 4e7fe386fca..b21e4482e9b 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -59,6 +59,7 @@ true true + false Microsoft.FSharp.Core.SR FSCore.resx diff --git a/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj b/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj index 4cf690ac79f..99477b7e4e9 100644 --- a/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj +++ b/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj @@ -48,7 +48,6 @@ - CompilerLocationUtils.fs @@ -60,7 +59,9 @@ - + + Microsoft.VisualStudio.FSharp.Interactive.SRProperties + true Properties Properties.resx diff --git a/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs b/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs new file mode 100644 index 00000000000..3e11c4e8d74 --- /dev/null +++ b/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Interactive + +type DisplayNameAttribute(resName) = + inherit System.ComponentModel.DisplayNameAttribute(SRProperties.GetString(resName)) + +type DescriptionAttribute(resName) = + inherit System.ComponentModel.DescriptionAttribute(SRProperties.GetString(resName)) + +type CategoryAttribute(resName) = + inherit System.ComponentModel.CategoryAttribute(SRProperties.GetString(resName)) diff --git a/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs b/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs index 5924a202ee6..0f4db5b4294 100644 --- a/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs +++ b/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs @@ -11,6 +11,7 @@ open System.Runtime.InteropServices open System.ComponentModel.Design open Microsoft.Win32 open Microsoft.VisualStudio +open Microsoft.VisualStudio.FSharp.Interactive open Microsoft.VisualStudio.OLE.Interop open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop @@ -37,24 +38,24 @@ module internal ContentType = type FsiPropertyPage() = inherit DialogPage() - [] - [] - [] + [] + [] + [] member this.FsiPreferAnyCPUVersion with get() = SessionsProperties.useAnyCpuVersion and set (x:bool) = SessionsProperties.useAnyCpuVersion <- x - [] - [] - [] + [] + [] + [] member this.FsiCommandLineArgs with get() = SessionsProperties.fsiArgs and set (x:string) = SessionsProperties.fsiArgs <- x - [] - [] - [] + [] + [] + [] member this.FsiShadowCopy with get() = SessionsProperties.fsiShadowCopy and set (x:bool) = SessionsProperties.fsiShadowCopy <- x - [] - [] - [] + [] + [] + [] member this.FsiDebugMode with get() = SessionsProperties.fsiDebugMode and set (x:bool) = SessionsProperties.fsiDebugMode <- x // CompletionSet diff --git a/vsintegration/src/FSharp.VS.FSI/srProperties.fs b/vsintegration/src/FSharp.VS.FSI/srProperties.fs deleted file mode 100644 index e88071d35be..00000000000 --- a/vsintegration/src/FSharp.VS.FSI/srProperties.fs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -module internal Microsoft.VisualStudio.FSharp.Interactive.SRProperties - -let private resources = lazy (new System.Resources.ResourceManager("Properties", System.Reflection.Assembly.GetExecutingAssembly())) - -let GetString(name:string) = - let s = resources.Value.GetString(name, System.Globalization.CultureInfo.CurrentUICulture) -#if DEBUG - if null = s then - System.Diagnostics.Debug.Assert(false, sprintf "**RESOURCE ERROR**: Resource token %s does not exist!" name) -#endif - s.Replace(@"\n", System.Environment.NewLine) - -[] -let FSharpInteractive64Bit = "FSharpInteractive64Bit" - -[] -let FSharpInteractive64BitDescr = "FSharpInteractive64BitDescr" - -[] -let FSharpInteractiveOptions = "FSharpInteractiveOptions" - -[] -let FSharpInteractiveOptionsDescr = "FSharpInteractiveOptionsDescr" - -[] -let FSharpInteractiveShadowCopyDescr = "FSharpInteractiveShadowCopyDescr" - -[] -let FSharpInteractiveShadowCopy = "FSharpInteractiveShadowCopy" - -[] -let FSharpInteractiveDebugMode = "FSharpInteractiveDebugMode" - -[] -let FSharpInteractiveDebugModeDescr = "FSharpInteractiveDebugModeDescr" - -[] -let FSharpInteractiveMisc = "FSharpInteractiveMisc" - -[] -let FSharpInteractiveDebugging = "FSharpInteractiveDebugging" - -type DisplayNameAttribute(resName) = - inherit System.ComponentModel.DisplayNameAttribute(GetString(resName)) - -type DescriptionAttribute(resName) = - inherit System.ComponentModel.DescriptionAttribute(GetString(resName)) - -type CategoryAttribute(resName) = - inherit System.ComponentModel.CategoryAttribute(GetString(resName)) \ No newline at end of file From 289dd15dc835ceccbd0a5ba54ac96960ae2d8f00 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Tue, 19 Sep 2017 16:37:18 -0700 Subject: [PATCH 07/16] don't generate non-string resources when <=netstandard1.6 --- src/FSharpSource.targets | 2 +- .../FSharp.Build/FSharpEmbedResXSource.fs | 32 +++++++++++++++---- .../FSharp.Build/Microsoft.FSharp.Targets | 2 +- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/FSharpSource.targets b/src/FSharpSource.targets index 869b0a8a689..188448b2a44 100644 --- a/src/FSharpSource.targets +++ b/src/FSharpSource.targets @@ -371,7 +371,7 @@ - + diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index f7a47ca56fa..b2864575437 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -18,6 +18,7 @@ type FSharpEmbedResXSource() = let mutable _embeddedText : ITaskItem[] = [||] let mutable _generatedSource : ITaskItem[] = [||] let mutable _outputPath : string = "" + let mutable _targetFramework : string = "" let boilerplate = @"// @@ -29,8 +30,9 @@ module internal {1} = type private C (_dummy:System.Object) = class end let mutable Culture = System.Globalization.CultureInfo.CurrentUICulture let ResourceManager = new System.Resources.ResourceManager(""{2}"", C(null).GetType().GetTypeInfo().Assembly) - let GetString(name:System.String) : System.String = ResourceManager.GetString(name, Culture) - let GetObject(name:System.String) : System.Object = ResourceManager.GetObject(name, Culture)" + let GetString(name:System.String) : System.String = ResourceManager.GetString(name, Culture)" + + let boilerplateGetObject = " let GetObject(name:System.String) : System.Object = ResourceManager.GetObject(name, Culture)" let generateSource (resx:string) (fullModuleName:string) (generateLegacy:bool) (generateLiteral:bool) = try @@ -40,7 +42,18 @@ module internal {1} = let parts = fullModuleName.Split('.') if parts.Length = 1 then ("global", parts.[0]) else (String.Join(".", parts, 0, parts.Length - 1), parts.[parts.Length - 1]) + let generateGetObject = + match _targetFramework with + | "netstandard1.0" + | "netstandard1.1" + | "netstandard1.2" + | "netstandard1.3" + | "netstandard1.4" + | "netstandard1.5" + | "netstandard1.6" -> false // these targets don't support the `ResourceManager.GetObject()` method + | _ -> true // other supported runtimes, do let sb = StringBuilder().AppendLine(String.Format(boilerplate, namespaceName, moduleName, justFileName)) + if generateGetObject then sb.AppendLine(boilerplateGetObject) |> ignore let sourcePath = Path.Combine(_outputPath, justFileName + ".fs") printMessage <| sprintf "Generating: %s" sourcePath let body = @@ -65,11 +78,14 @@ module internal {1} = | (true, true) -> sprintf " []\n let %s = \"%s\"" identifier name | (true, false) -> sprintf " let %s = \"%s\"" identifier name // the [] attribute can't be used for FSharp.Core | (false, _) -> - let accessorFunction = match node.Attribute(xname "type") with - | null -> "GetString" - | _ -> "GetObject" + let isStringResource = match node.Attribute(xname "type") with + | null -> true + | _ -> false + match (isStringResource, generateGetObject) with + | (true, _) -> sprintf " let %s() = GetString(\"%s\")" identifier name + | (false, true) -> sprintf " let %s() = GetObject(\"%s\")" identifier name + | (false, false) -> "" // the target runtime doesn't support non-string resources // TODO: When calling the `GetObject` version, parse the `type` attribute to discover the proper return type - sprintf " let %s() = %s(\"%s\")" identifier accessorFunction name sb.AppendLine().Append(commentBody).AppendLine(accessorBody) ) sb File.WriteAllText(sourcePath, body.ToString()) @@ -89,6 +105,10 @@ module internal {1} = with get() = _outputPath and set(value) = _outputPath <- value + member this.TargetFramework + with get() = _targetFramework + and set(value) = _targetFramework <- value + [] member this.GeneratedSource with get() = _generatedSource diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index b7165c57868..fb0957e115f 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -177,7 +177,7 @@ this file. - + From c1ab08a83922caf7d92dc7077cdfbcbed75eeb09 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 10:11:57 -0700 Subject: [PATCH 08/16] update baseline error message for tests The error output should be the exception message, not the exception type. --- tests/fsharp/core/printing/z.output.test.1000.stdout.bsl | 6 +++--- tests/fsharp/core/printing/z.output.test.200.stdout.bsl | 6 +++--- tests/fsharp/core/printing/z.output.test.default.stdout.bsl | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl b/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl index 882e4de4d56..1f9224b67b7 100644 --- a/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl @@ -1623,15 +1623,15 @@ val catch : f:(unit -> 'a) -> Either<'a,(string * string)> val seqFindIndexFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") val seqFindFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") val seqPickFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") module Regression5218 = begin val t1 : int = 1 val t2 : int * int = (1, 2) diff --git a/tests/fsharp/core/printing/z.output.test.200.stdout.bsl b/tests/fsharp/core/printing/z.output.test.200.stdout.bsl index 61a06e0b727..0877fcb8002 100644 --- a/tests/fsharp/core/printing/z.output.test.200.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.200.stdout.bsl @@ -872,15 +872,15 @@ val catch : f:(unit -> 'a) -> Either<'a,(string * string)> val seqFindIndexFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") val seqFindFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") val seqPickFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") module Regression5218 = begin val t1 : int = 1 val t2 : int * int = (1, 2) diff --git a/tests/fsharp/core/printing/z.output.test.default.stdout.bsl b/tests/fsharp/core/printing/z.output.test.default.stdout.bsl index 2fa1a95c0d9..fab8d8dbaa8 100644 --- a/tests/fsharp/core/printing/z.output.test.default.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.default.stdout.bsl @@ -5149,15 +5149,15 @@ val catch : f:(unit -> 'a) -> Either<'a,(string * string)> val seqFindIndexFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") val seqFindFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") val seqPickFailure : Either = That ("System.Collections.Generic.KeyNotFoundException", - "Exception of type 'System.Collections.Generic.KeyNotFoundExce"+[18 chars]) + "An index satisfying the predicate was not found in the collection.") module Regression5218 = begin val t1 : int = 1 val t2 : int * int = (1, 2) From decdcb0430fc7d54bb76839e442031c03a1a6208 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 11:28:18 -0700 Subject: [PATCH 09/16] perform up-to-date check before generating *.fs from *.resx --- .../FSharp.Build/FSharpEmbedResXSource.fs | 111 ++++++++++-------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index b2864575437..8a315b06d79 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -38,59 +38,66 @@ module internal {1} = try let printMessage = printfn "FSharpEmbedResXSource: %s" let justFileName = Path.GetFileNameWithoutExtension(resx) - let namespaceName, moduleName = - let parts = fullModuleName.Split('.') - if parts.Length = 1 then ("global", parts.[0]) - else (String.Join(".", parts, 0, parts.Length - 1), parts.[parts.Length - 1]) - let generateGetObject = - match _targetFramework with - | "netstandard1.0" - | "netstandard1.1" - | "netstandard1.2" - | "netstandard1.3" - | "netstandard1.4" - | "netstandard1.5" - | "netstandard1.6" -> false // these targets don't support the `ResourceManager.GetObject()` method - | _ -> true // other supported runtimes, do - let sb = StringBuilder().AppendLine(String.Format(boilerplate, namespaceName, moduleName, justFileName)) - if generateGetObject then sb.AppendLine(boilerplateGetObject) |> ignore let sourcePath = Path.Combine(_outputPath, justFileName + ".fs") - printMessage <| sprintf "Generating: %s" sourcePath - let body = - let xname = XName.op_Implicit - XDocument.Load(resx).Descendants(xname "data") - |> Seq.fold (fun (sb:StringBuilder) (node:XElement) -> - let name = - match node.Attribute(xname "name") with - | null -> failwith "Missing resource name" - | attr -> attr.Value - let docComment = - match node.Elements(xname "value").FirstOrDefault() with - | null -> failwith <| sprintf "Missing resource value for '%s'" name - | element -> element.Value.Trim() - let identifier = if Char.IsLetter(name.[0]) || name.[0] = '_' then name else "_" + name - let commentBody = - XElement(xname "summary", docComment).ToString().Split([|"\r\n"; "\r"; "\n"|], StringSplitOptions.None) - |> Array.fold (fun (sb:StringBuilder) line -> sb.AppendLine(" /// " + line)) (StringBuilder()) - // add the resource - let accessorBody = - match (generateLegacy, generateLiteral) with - | (true, true) -> sprintf " []\n let %s = \"%s\"" identifier name - | (true, false) -> sprintf " let %s = \"%s\"" identifier name // the [] attribute can't be used for FSharp.Core - | (false, _) -> - let isStringResource = match node.Attribute(xname "type") with - | null -> true - | _ -> false - match (isStringResource, generateGetObject) with - | (true, _) -> sprintf " let %s() = GetString(\"%s\")" identifier name - | (false, true) -> sprintf " let %s() = GetObject(\"%s\")" identifier name - | (false, false) -> "" // the target runtime doesn't support non-string resources - // TODO: When calling the `GetObject` version, parse the `type` attribute to discover the proper return type - sb.AppendLine().Append(commentBody).AppendLine(accessorBody) - ) sb - File.WriteAllText(sourcePath, body.ToString()) - printMessage <| sprintf "Done: %s" sourcePath - Some(sourcePath) + + // simple up-to-date check + if File.Exists(resx) && File.Exists(sourcePath) && + File.GetLastWriteTime(resx) <= File.GetLastWriteTime(sourcePath) then + printMessage (sprintf "Skipping generation: '%s' since it is up-to-date." sourcePath) + Some(sourcePath) + else + let namespaceName, moduleName = + let parts = fullModuleName.Split('.') + if parts.Length = 1 then ("global", parts.[0]) + else (String.Join(".", parts, 0, parts.Length - 1), parts.[parts.Length - 1]) + let generateGetObject = + match _targetFramework with + | "netstandard1.0" + | "netstandard1.1" + | "netstandard1.2" + | "netstandard1.3" + | "netstandard1.4" + | "netstandard1.5" + | "netstandard1.6" -> false // these targets don't support the `ResourceManager.GetObject()` method + | _ -> true // other supported runtimes, do + let sb = StringBuilder().AppendLine(String.Format(boilerplate, namespaceName, moduleName, justFileName)) + if generateGetObject then sb.AppendLine(boilerplateGetObject) |> ignore + printMessage <| sprintf "Generating: %s" sourcePath + let body = + let xname = XName.op_Implicit + XDocument.Load(resx).Descendants(xname "data") + |> Seq.fold (fun (sb:StringBuilder) (node:XElement) -> + let name = + match node.Attribute(xname "name") with + | null -> failwith "Missing resource name" + | attr -> attr.Value + let docComment = + match node.Elements(xname "value").FirstOrDefault() with + | null -> failwith <| sprintf "Missing resource value for '%s'" name + | element -> element.Value.Trim() + let identifier = if Char.IsLetter(name.[0]) || name.[0] = '_' then name else "_" + name + let commentBody = + XElement(xname "summary", docComment).ToString().Split([|"\r\n"; "\r"; "\n"|], StringSplitOptions.None) + |> Array.fold (fun (sb:StringBuilder) line -> sb.AppendLine(" /// " + line)) (StringBuilder()) + // add the resource + let accessorBody = + match (generateLegacy, generateLiteral) with + | (true, true) -> sprintf " []\n let %s = \"%s\"" identifier name + | (true, false) -> sprintf " let %s = \"%s\"" identifier name // the [] attribute can't be used for FSharp.Core + | (false, _) -> + let isStringResource = match node.Attribute(xname "type") with + | null -> true + | _ -> false + match (isStringResource, generateGetObject) with + | (true, _) -> sprintf " let %s() = GetString(\"%s\")" identifier name + | (false, true) -> sprintf " let %s() = GetObject(\"%s\")" identifier name + | (false, false) -> "" // the target runtime doesn't support non-string resources + // TODO: When calling the `GetObject` version, parse the `type` attribute to discover the proper return type + sb.AppendLine().Append(commentBody).AppendLine(accessorBody) + ) sb + File.WriteAllText(sourcePath, body.ToString()) + printMessage <| sprintf "Done: %s" sourcePath + Some(sourcePath) with e -> printf "An exception occurred when processing '%s'\n%s" resx (e.ToString()) None From 71c0931877c8ab3221bbab170452a171f08a3932 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 13:21:43 -0700 Subject: [PATCH 10/16] remove non-idiomatic fold for an array comprehension --- .../FSharp.Build/FSharpEmbedResXSource.fs | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index 8a315b06d79..1408d3810a3 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -132,20 +132,19 @@ module internal {1} = match item.GetMetadata(metadataName) with | value when String.IsNullOrWhiteSpace(value) -> defaultValue | value -> String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) = 0 - let generatedFiles, generatedResult = - this.EmbeddedResource - |> Array.filter (getBooleanMetadata "GenerateSource" false) - |> Array.fold (fun (resultList, aggregateResult) item -> - let moduleName = - match item.GetMetadata("GeneratedModuleName") with - | null -> Path.GetFileNameWithoutExtension(item.ItemSpec) - | value -> value - let generateLegacy = getBooleanMetadata "GenerateLegacyCode" false item - let generateLiteral = getBooleanMetadata "GenerateLiterals" true item - match generateSource item.ItemSpec moduleName generateLegacy generateLiteral with - | Some (source) -> ((source :: resultList), aggregateResult) - | None -> (resultList, false) - ) ([], true) - let generatedSources = generatedFiles |> List.map (fun item -> TaskItem(item) :> ITaskItem) - _generatedSource <- generatedSources |> List.rev |> List.toArray - generatedResult + let mutable success = true + let generatedSource = + [| for item in this.EmbeddedResource do + if getBooleanMetadata "GenerateSource" false item then + let moduleName = + match item.GetMetadata("GeneratedModuleName") with + | null -> Path.GetFileNameWithoutExtension(item.ItemSpec) + | value -> value + let generateLegacy = getBooleanMetadata "GenerateLegacyCode" false item + let generateLiteral = getBooleanMetadata "GenerateLiterals" true item + match generateSource item.ItemSpec moduleName generateLegacy generateLiteral with + | Some (source) -> yield TaskItem(source) :> ITaskItem + | None -> success <- false + |] + _generatedSource <- generatedSource + success From 1245d590e4a49a467b38caf8c7aa13bfb9cc01e8 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 14:07:43 -0700 Subject: [PATCH 11/16] correct newline replacement --- vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index 5ce8b6668f0..53f35fa7d05 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -1938,7 +1938,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem ) |> ignore Marshal.ThrowExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED) let result = - VsShellUtilities.ShowMessageBox(node.Site, FSharpSR.NeedReloadToChangeTargetFx().Replace("\n", Environment.NewLine), + VsShellUtilities.ShowMessageBox(node.Site, FSharpSR.NeedReloadToChangeTargetFx().Replace(@"\n", Environment.NewLine), null, OLEMSGICON.OLEMSGICON_QUERY, OLEMSGBUTTON.OLEMSGBUTTON_YESNO, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST) if result <> NativeMethods.IDYES then @@ -2466,7 +2466,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem match location with | Above -> FSharpSR.FileCannotBePlacedBodyAbove() | Below -> FSharpSR.FileCannotBePlacedBodyBelow() - |> (fun s -> s.Replace("\n", Environment.NewLine)) + |> (fun s -> s.Replace(@"\n", Environment.NewLine)) let entireMessage = String.Format(bodyString, relPath, relTargetPath, message) VsShellUtilities.ShowMessageBox(root.Site, title, entireMessage, icon, buttons, defaultButton) |> ignore From 720963049c31274c1d6407aa06aee23befb83a55 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 14:14:47 -0700 Subject: [PATCH 12/16] output more friendly error message --- src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index 1408d3810a3..dd8f4223cd4 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -69,7 +69,7 @@ module internal {1} = |> Seq.fold (fun (sb:StringBuilder) (node:XElement) -> let name = match node.Attribute(xname "name") with - | null -> failwith "Missing resource name" + | null -> failwith (sprintf "Missing resource name on element '%s'" (node.ToString())) | attr -> attr.Value let docComment = match node.Elements(xname "value").FirstOrDefault() with From 4f321fdd31976d7db8a0179efa5e5dde7232c483 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 14:40:48 -0700 Subject: [PATCH 13/16] throw if boolean value isn't explicitly `true` or `false` --- src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index dd8f4223cd4..473d9de2773 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -131,7 +131,11 @@ module internal {1} = let getBooleanMetadata (metadataName:string) (defaultValue:bool) (item:ITaskItem) = match item.GetMetadata(metadataName) with | value when String.IsNullOrWhiteSpace(value) -> defaultValue - | value -> String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) = 0 + | value -> + match value.ToLowerInvariant() with + | "true" -> true + | "false" -> false + | _ -> failwith (sprintf "Expected boolean value for '%s' found '%s'" metadataName value) let mutable success = true let generatedSource = [| for item in this.EmbeddedResource do From c89546f4c1ccad2947b66df0cb6c6d5d2552b304 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 14:50:10 -0700 Subject: [PATCH 14/16] only generate object resource code on non `netstandard1.*` and `netcoreapp1.*` platforms --- src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index 473d9de2773..3026421511a 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -50,16 +50,7 @@ module internal {1} = let parts = fullModuleName.Split('.') if parts.Length = 1 then ("global", parts.[0]) else (String.Join(".", parts, 0, parts.Length - 1), parts.[parts.Length - 1]) - let generateGetObject = - match _targetFramework with - | "netstandard1.0" - | "netstandard1.1" - | "netstandard1.2" - | "netstandard1.3" - | "netstandard1.4" - | "netstandard1.5" - | "netstandard1.6" -> false // these targets don't support the `ResourceManager.GetObject()` method - | _ -> true // other supported runtimes, do + let generateGetObject = not (_targetFramework.StartsWith("netstandard1.") || _targetFramework.StartsWith("netcoreapp1.")) let sb = StringBuilder().AppendLine(String.Format(boilerplate, namespaceName, moduleName, justFileName)) if generateGetObject then sb.AppendLine(boilerplateGetObject) |> ignore printMessage <| sprintf "Generating: %s" sourcePath From 7594f7ffd675ab51e1e5d095232136e54dbfdaf5 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Wed, 20 Sep 2017 16:09:27 -0700 Subject: [PATCH 15/16] ensure FSharp.Core specifies a target framework for resource generaton --- src/FSharpSource.Profiles.targets | 1 + src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/FSharpSource.Profiles.targets b/src/FSharpSource.Profiles.targets index c2c58cdf812..adafba0eae3 100644 --- a/src/FSharpSource.Profiles.targets +++ b/src/FSharpSource.Profiles.targets @@ -56,6 +56,7 @@ $(DefineConstants);FX_RESHAPED_MSBUILD $(DefineConstants);FSI_TODO_NETCORE $(OtherFlags) --simpleresolution + netstandard1.6 diff --git a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs index 3026421511a..54045b642f0 100644 --- a/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs +++ b/src/fsharp/FSharp.Build/FSharpEmbedResXSource.fs @@ -51,6 +51,7 @@ module internal {1} = if parts.Length = 1 then ("global", parts.[0]) else (String.Join(".", parts, 0, parts.Length - 1), parts.[parts.Length - 1]) let generateGetObject = not (_targetFramework.StartsWith("netstandard1.") || _targetFramework.StartsWith("netcoreapp1.")) + printMessage (sprintf "Generating code for target framework %s" _targetFramework) let sb = StringBuilder().AppendLine(String.Format(boilerplate, namespaceName, moduleName, justFileName)) if generateGetObject then sb.AppendLine(boilerplateGetObject) |> ignore printMessage <| sprintf "Generating: %s" sourcePath From 18ea1fa2e66075b540c4775f94a5387ffb1f223e Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Thu, 21 Sep 2017 15:28:46 -0700 Subject: [PATCH 16/16] rename attributes to be non-ambiguous and properly include them --- .../src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj | 1 + .../FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs | 6 ++--- .../src/FSharp.VS.FSI/fsiLanguageService.fs | 24 +++++++++---------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj b/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj index 99477b7e4e9..080745543a1 100644 --- a/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj +++ b/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj @@ -48,6 +48,7 @@ + CompilerLocationUtils.fs diff --git a/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs b/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs index 3e11c4e8d74..78442f823b1 100644 --- a/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs +++ b/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.Attributes.fs @@ -2,11 +2,11 @@ namespace Microsoft.VisualStudio.FSharp.Interactive -type DisplayNameAttribute(resName) = +type internal ResourceDisplayNameAttribute(resName) = inherit System.ComponentModel.DisplayNameAttribute(SRProperties.GetString(resName)) -type DescriptionAttribute(resName) = +type internal ResourceDescriptionAttribute(resName) = inherit System.ComponentModel.DescriptionAttribute(SRProperties.GetString(resName)) -type CategoryAttribute(resName) = +type internal ResourceCategoryAttribute(resName) = inherit System.ComponentModel.CategoryAttribute(SRProperties.GetString(resName)) diff --git a/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs b/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs index 0f4db5b4294..62d2cf7efe9 100644 --- a/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs +++ b/vsintegration/src/FSharp.VS.FSI/fsiLanguageService.fs @@ -38,24 +38,24 @@ module internal ContentType = type FsiPropertyPage() = inherit DialogPage() - [] - [] - [] + [] + [] + [] member this.FsiPreferAnyCPUVersion with get() = SessionsProperties.useAnyCpuVersion and set (x:bool) = SessionsProperties.useAnyCpuVersion <- x - [] - [] - [] + [] + [] + [] member this.FsiCommandLineArgs with get() = SessionsProperties.fsiArgs and set (x:string) = SessionsProperties.fsiArgs <- x - [] - [] - [] + [] + [] + [] member this.FsiShadowCopy with get() = SessionsProperties.fsiShadowCopy and set (x:bool) = SessionsProperties.fsiShadowCopy <- x - [] - [] - [] + [] + [] + [] member this.FsiDebugMode with get() = SessionsProperties.fsiDebugMode and set (x:bool) = SessionsProperties.fsiDebugMode <- x // CompletionSet