diff --git a/FSharpBuild.Directory.Build.targets b/FSharpBuild.Directory.Build.targets index 7548cef7acf7bfc31f43349d5a1a60f672d1cfdb..3132ba1c9701cc72925116892d5c9fc44bb12da4 100644 --- a/FSharpBuild.Directory.Build.targets +++ b/FSharpBuild.Directory.Build.targets @@ -1,4 +1,5 @@ + @@ -8,7 +9,7 @@ + BeforeTargets="AssignTargetPaths;BeforeBuild;GenerateFSharpTextResources"> <__TargetFilePath>@(NoneSubstituteText->'$(IntermediateOutputPath)%(Filename)%(Extension)') @@ -20,16 +21,19 @@ <_CopyToOutputDirectory Condition="'%(NoneSubstituteText.CopyToOutputDirectory)' != ''">%(NoneSubstituteText.CopyToOutputDirectory) <_CopyToOutputDirectory Condition="'%(NoneSubstituteText.CopyToOutputDirectory)' == ''">Never + + <_IncludeInVsix>false + <_IncludeInVsix Condition="'%(NoneSubstituteText.IncludeInVsix)' == 'true'">true - - + + @@ -61,4 +65,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fcs/build.fsx b/fcs/build.fsx index 1c2528dd2e0ccc0f0a223ceb0f36ec6d25ee9522..af21298e7abfbc6bf628440787d692568bb2f095 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -66,16 +66,16 @@ Target.create "Build" (fun _ -> runDotnet __SOURCE_DIRECTORY__ "build" "../src/buildtools/buildtools.proj -v n -c Proto" let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/netcoreapp2.1/fslex.dll" let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/netcoreapp2.1/fsyacc.dll" - runDotnet __SOURCE_DIRECTORY__ "build" (sprintf "FSharp.Compiler.Service.sln -v n -c Release /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) + runDotnet __SOURCE_DIRECTORY__ "build" (sprintf "FSharp.Compiler.Service.sln -nodereuse:false -v n -c Release /p:DisableCompilerRedirection=true /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath) ) Target.create "Test" (fun _ -> // This project file is used for the netcoreapp2.0 tests to work out reference sets - runDotnet __SOURCE_DIRECTORY__ "build" "../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true" + runDotnet __SOURCE_DIRECTORY__ "build" "../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -nodereuse:false -v n /restore /p:DisableCompilerRedirection=true" // Now run the tests let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml") - runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -v n -c Release --test-adapter-path . --logger \"nunit;LogFilePath=%s\"" logFilePath) + runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -nodereuse:false -v n -c Release --test-adapter-path . --logger \"nunit;LogFilePath=%s\"" logFilePath) ) Target.create "NuGet" (fun _ -> diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 76b9c7043e9915bcf9cf5aba29849d6385452109..f427453df992bd15741aa5452e6a04b91026ccdd 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -26,6 +26,7 @@ + diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index 8421c8ea504bf7ff6b9744d3171a3054cb364485..0b51d7204f69a0e6cb06e21545bce35ed7196725 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -29,6 +29,7 @@ this file. + true diff --git a/src/fsharp/FSharp.Build/SubstituteText.fs b/src/fsharp/FSharp.Build/SubstituteText.fs new file mode 100644 index 0000000000000000000000000000000000000000..16b8eab524538a229a15ad602dcd1034200cd783 --- /dev/null +++ b/src/fsharp/FSharp.Build/SubstituteText.fs @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Build + +open System +open System.Collections +open System.IO +open Microsoft.Build.Framework +open Microsoft.Build.Utilities + +type SubstituteText () = + + let mutable _buildEngine : IBuildEngine = null + let mutable _hostObject : ITaskHost = null + + let mutable copiedFiles = new ResizeArray() + let mutable embeddedResources : ITaskItem[] = [||] + + [] + member this.EmbeddedResources + with get() = embeddedResources + and set(value) = embeddedResources <- value + + [] + member this.CopiedFiles + with get() = copiedFiles.ToArray() + + 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() = + copiedFiles.Clear() + if not(isNull embeddedResources) then + for item in embeddedResources do + // Update ITaskItem metadata to point to new location + let sourcePath = item.GetMetadata("FullPath") + + let pattern1 = item.GetMetadata("Pattern1") + let pattern2 = item.GetMetadata("Pattern2") + + // Is there any replacement to do? + if not (String.IsNullOrWhiteSpace(pattern1) && String.IsNullOrWhiteSpace(pattern2)) then + if not(String.IsNullOrWhiteSpace(sourcePath)) then + try + let getTargetPathFrom key = + let md = item.GetMetadata(key) + let path = Path.GetDirectoryName(md) + let filename = Path.GetFileName(md) + let target = Path.Combine(path, @"..\resources", filename) + target + + // Copy from the location specified in Identity + let sourcePath=item.GetMetadata("Identity") + + // Copy to the location specified in TargetPath unless no TargetPath is provided, then use Identity + let targetPath= + let identityPath = getTargetPathFrom "Identity" + let intermediateTargetPath = item.GetMetadata("IntermediateTargetPath") + if not (String.IsNullOrWhiteSpace(intermediateTargetPath)) then + let filename = Path.GetFileName(identityPath) + let target = Path.Combine(intermediateTargetPath, filename) + target + else + identityPath + + item.ItemSpec <- targetPath + + // Transform file + let mutable contents = File.ReadAllText(sourcePath) + if not (String.IsNullOrWhiteSpace(pattern1)) then + let replacement = item.GetMetadata("Replacement1") + contents <- contents.Replace(pattern1, replacement) + if not (String.IsNullOrWhiteSpace(pattern2)) then + let replacement = item.GetMetadata("Replacement2") + contents <- contents.Replace(pattern2, replacement) + + let directory = Path.GetDirectoryName(targetPath) + if not(Directory.Exists(directory)) then + Directory.CreateDirectory(directory) |>ignore + + File.WriteAllText(targetPath, contents) + with + | _ -> () + + copiedFiles.Add(item) + true diff --git a/src/fsharp/LexFilter.fs b/src/fsharp/LexFilter.fs index a998dfd69947f41bac6737ad647dc59f0cb5f886..e2d316bd29a6a53f60c9adf888c61052f39d48c8 100755 --- a/src/fsharp/LexFilter.fs +++ b/src/fsharp/LexFilter.fs @@ -399,39 +399,66 @@ type LexbufState(startPos: Position, member x.EndPos = endPos member x.PastEOF = pastEOF -[] -type PositionTuple = - val X: Position - val Y: Position - new (x: Position, y: Position) = { X = x; Y = y } - /// Used to save the state related to a token +/// Treat as though this is read-only. [] type TokenTup = - val Token : token - val LexbufState : LexbufState - val LastTokenPos: PositionTuple + // This is mutable for performance reasons. + val mutable Token : token + val mutable LexbufState : LexbufState + val mutable LastTokenPos: Position new (token, state, lastTokenPos) = { Token=token; LexbufState=state;LastTokenPos=lastTokenPos } /// Returns starting position of the token member x.StartPos = x.LexbufState.StartPos /// Returns end position of the token member x.EndPos = x.LexbufState.EndPos - + +type TokenTupPool() = + + /// Arbitrary. + /// When parsing the compiler's source files, the pool didn't come close to reaching this limit. + /// Therefore, this seems like a reasonable limit to handle 99% of cases. + [] + let maxSize = 100 + + let stack = System.Collections.Generic.Stack(Array.init maxSize (fun _ -> TokenTup(Unchecked.defaultof<_>, Unchecked.defaultof<_>, Unchecked.defaultof<_>))) + + member _.Rent() = + if stack.Count = 0 then + assert false + TokenTup(Unchecked.defaultof<_>, Unchecked.defaultof<_>, Unchecked.defaultof<_>) + else + stack.Pop() + + member _.Return(x: TokenTup) = + x.Token <- Unchecked.defaultof<_> + x.LexbufState <- Unchecked.defaultof<_> + x.LastTokenPos <- Unchecked.defaultof<_> + if stack.Count >= maxSize then + assert false + else + stack.Push x + /// Returns a token 'tok' with the same position as this token - member x.UseLocation tok = + member pool.UseLocation(x: TokenTup, tok) = let tokState = x.LexbufState - TokenTup(tok, LexbufState(tokState.StartPos, tokState.EndPos, false), x.LastTokenPos) + let tokTup = pool.Rent() + tokTup.Token <- tok + tokTup.LexbufState <- LexbufState(tokState.StartPos, tokState.EndPos, false) + tokTup.LastTokenPos <- x.LastTokenPos + tokTup /// Returns a token 'tok' with the same position as this token, except that /// it is shifted by specified number of characters from the left and from the right /// Note: positive value means shift to the right in both cases - member x.UseShiftedLocation(tok, shiftLeft, shiftRight) = - let tokState = x.LexbufState - TokenTup(tok, LexbufState(tokState.StartPos.ShiftColumnBy shiftLeft, - tokState.EndPos.ShiftColumnBy shiftRight, false), x.LastTokenPos) - - + member pool.UseShiftedLocation(x: TokenTup, tok, shiftLeft, shiftRight) = + let tokState = x.LexbufState + let tokTup = pool.Rent() + tokTup.Token <- tok + tokTup.LexbufState <- LexbufState(tokState.StartPos.ShiftColumnBy shiftLeft, tokState.EndPos.ShiftColumnBy shiftRight, false) + tokTup.LastTokenPos <- x.LastTokenPos + tokTup //---------------------------------------------------------------------------- // Utilities for the tokenizer that are needed in other places @@ -541,6 +568,12 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | Parser.EOF _ -> tokenTup.LexbufState.StartPos.ColumnMinusOne | _ -> tokenTup.LexbufState.StartPos + //---------------------------------------------------------------------------- + // TokenTup pool + //-------------------------------------------------------------------------- + + let pool = TokenTupPool() + //---------------------------------------------------------------------------- // Part II. The state of the new lex stream object. //-------------------------------------------------------------------------- @@ -552,7 +585,6 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, let runWrappedLexerInConsistentLexbufState() = let state = if haveLexbufState then savedLexbufState else getLexbufState() setLexbufState state - let lastTokenStart = state.StartPos let lastTokenEnd = state.EndPos let token = lexer lexbuf // Now we've got the token, remember the lexbuf state, associating it with the token @@ -560,7 +592,12 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, let tokenLexbufState = getLexbufState() savedLexbufState <- tokenLexbufState haveLexbufState <- true - TokenTup(token, tokenLexbufState, PositionTuple(lastTokenStart, lastTokenEnd)) + + let tokenTup = pool.Rent() + tokenTup.Token <- token + tokenTup.LexbufState <- tokenLexbufState + tokenTup.LastTokenPos <- lastTokenEnd + tokenTup //---------------------------------------------------------------------------- // Fetch a raw token, either from the old lexer or from our delayedStack @@ -898,7 +935,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // and insert a HIGH_PRECEDENCE_PAREN_APP if not hasAfterOp && (match nextTokenIsAdjacentLParenOrLBrack lookaheadTokenTup with Some LPAREN -> true | _ -> false) then let dotTokenTup = peekNextTokenTup() - stack := (dotTokenTup.UseLocation(HIGH_PRECEDENCE_PAREN_APP), false) :: !stack + stack := (pool.UseLocation(dotTokenTup, HIGH_PRECEDENCE_PAREN_APP), false) :: !stack true | INFIX_COMPARE_OP (TyparsCloseOp(greaters, afterOp)) -> let nParen = nParen - greaters.Length @@ -912,7 +949,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // and insert a HIGH_PRECEDENCE_PAREN_APP if afterOp.IsNone && (match nextTokenIsAdjacentLParenOrLBrack lookaheadTokenTup with Some LPAREN -> true | _ -> false) then let dotTokenTup = peekNextTokenTup() - stack := (dotTokenTup.UseLocation(HIGH_PRECEDENCE_PAREN_APP), false) :: !stack + stack := (pool.UseLocation(dotTokenTup, HIGH_PRECEDENCE_PAREN_APP), false) :: !stack true | (LPAREN | LESS _ | LBRACK | LBRACK_LESS | INFIX_COMPARE_OP " scanAhead (nParen+1) @@ -967,22 +1004,27 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, if smash then match tokenTup.Token with | INFIX_COMPARE_OP " - delayToken (tokenTup.UseShiftedLocation(INFIX_STAR_DIV_MOD_OP "/", 1, 0)) - delayToken (tokenTup.UseShiftedLocation(LESS res, 0, -1)) + delayToken (pool.UseShiftedLocation(tokenTup, INFIX_STAR_DIV_MOD_OP "/", 1, 0)) + delayToken (pool.UseShiftedLocation(tokenTup, LESS res, 0, -1)) + pool.Return tokenTup | GREATER_BAR_RBRACK -> - delayToken (tokenTup.UseShiftedLocation(BAR_RBRACK, 1, 0)) - delayToken (tokenTup.UseShiftedLocation(GREATER res, 0, -2)) + delayToken (pool.UseShiftedLocation(tokenTup, BAR_RBRACK, 1, 0)) + delayToken (pool.UseShiftedLocation(tokenTup, GREATER res, 0, -2)) + pool.Return tokenTup | GREATER_RBRACK -> - delayToken (tokenTup.UseShiftedLocation(RBRACK, 1, 0)) - delayToken (tokenTup.UseShiftedLocation(GREATER res, 0, -1)) + delayToken (pool.UseShiftedLocation(tokenTup, RBRACK, 1, 0)) + delayToken (pool.UseShiftedLocation(tokenTup, GREATER res, 0, -1)) + pool.Return tokenTup | GREATER _ -> - delayToken (tokenTup.UseLocation(GREATER res)) + delayToken (pool.UseLocation(tokenTup, GREATER res)) + pool.Return tokenTup | (INFIX_COMPARE_OP (TyparsCloseOp(greaters, afterOp) as opstr)) -> match afterOp with | None -> () - | Some tok -> delayToken (tokenTup.UseShiftedLocation(tok, greaters.Length, 0)) + | Some tok -> delayToken (pool.UseShiftedLocation(tokenTup, tok, greaters.Length, 0)) for i = greaters.Length - 1 downto 0 do - delayToken (tokenTup.UseShiftedLocation(greaters.[i] res, i, -opstr.Length + i + 1)) + delayToken (pool.UseShiftedLocation(tokenTup, greaters.[i] res, i, -opstr.Length + i + 1)) + pool.Return tokenTup | _ -> delayToken tokenTup else delayToken tokenTup) @@ -1109,7 +1151,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // span of inserted token lasts from the col + 1 of the prev token // to the beginning of current token let lastTokenPos = - let pos = tokenTup.LastTokenPos.Y + let pos = tokenTup.LastTokenPos pos.ShiftColumnBy 1 returnToken (lexbufStateForInsertedDummyTokens (lastTokenPos, tokenTup.LexbufState.StartPos)) tok @@ -1235,7 +1277,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, popCtxt() effectsToDo <- (fun() -> if debug then dprintf "--> because %s is coming, inserting OBLOCKEND\n" keywordName - delayTokenNoProcessing (tokenTup.UseLocation OBLOCKEND)) :: effectsToDo + delayTokenNoProcessing (pool.UseLocation(tokenTup, OBLOCKEND))) :: effectsToDo | CtxtSeqBlock(_, _, NoAddBlockEnd) -> if debug then dprintf "--> because %s is coming, popping CtxtSeqBlock\n" keywordName popCtxt() @@ -1243,7 +1285,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, popCtxt() effectsToDo <- (fun() -> if debug then dprintf "--> because %s is coming, inserting ORIGHT_BLOCK_END\n" keywordName - delayTokenNoProcessing (tokenTup.UseLocation(ORIGHT_BLOCK_END))) :: effectsToDo + delayTokenNoProcessing (pool.UseLocation(tokenTup, ORIGHT_BLOCK_END))) :: effectsToDo | CtxtVanilla _ -> if debug then dprintf "--> because %s is coming, popping CtxtVanilla\n" keywordName popCtxt() @@ -1253,12 +1295,16 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // Why _six_ TYPE_COMING_SOON? It's rather arbitrary, this means we can recover from up to six unmatched parens before failing. The unit tests (with 91609 in the name) demonstrate this. // Don't "delayToken tokenTup", we are replacing it, so consume it. if debug then dprintf "inserting 6 copies of %+A before %+A\n" comingSoon isHere - delayTokenNoProcessing (tokenTup.UseLocation isHere) + delayTokenNoProcessing (pool.UseLocation(tokenTup, isHere)) for i in 1..6 do - delayTokenNoProcessing (tokenTup.UseLocation comingSoon) + delayTokenNoProcessing (pool.UseLocation(tokenTup, comingSoon)) for e in List.rev effectsToDo do e() // push any END tokens after pushing the TYPE_IS_HERE and TYPE_COMING_SOON stuff, so that they come before those in the token stream + let returnToken tokenLexbufState token = + pool.Return tokenTup + returnToken tokenLexbufState token + match token, offsideStack with // inserted faux tokens need no other processing | _ when tokensThatNeedNoProcessingCount > 0 -> @@ -1279,7 +1325,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // reset on ';;' rule. A ';;' terminates ALL entries | SEMICOLON_SEMICOLON, [] -> if debug then dprintf ";; scheduling a reset\n" - delayToken(tokenTup.UseLocation ORESET) + delayToken(pool.UseLocation(tokenTup, ORESET)) returnToken tokenLexbufState SEMICOLON_SEMICOLON | ORESET, [] -> @@ -1287,6 +1333,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // NOTE: The parser thread of F# Interactive will often be blocked on this call, e.g. after an entry has been // processed and we're waiting for the first token of the next entry. peekInitial() |> ignore + pool.Return tokenTup hwTokenFetch true @@ -1300,7 +1347,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, if tokenStartCol < offsidePos.Column then warn tokenTup (FSComp.SR.lexfltIncorrentIndentationOfIn()) popCtxt() // Make sure we queue a dummy token at this position to check if any other pop rules apply - delayToken(tokenTup.UseLocation(ODUMMY token)) + delayToken(pool.UseLocation(tokenTup, ODUMMY token)) returnToken tokenLexbufState (if blockLet then ODECLEND else token) // Balancing rule. Encountering a 'done' balances with a 'do'. i.e. even a non-offside 'done' closes a 'do' @@ -1309,7 +1356,8 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, if debug then dprintf "DONE at %a terminates CtxtDo(offsidePos=%a)\n" outputPos tokenStartPos outputPos offsidePos popCtxt() // reprocess as the DONE may close a DO context - delayToken(tokenTup.UseLocation ODECLEND) + delayToken(pool.UseLocation(tokenTup, ODECLEND)) + pool.Return tokenTup hwTokenFetch useBlockRule // Balancing rule. Encountering a ')' or '}' balances with a '(' or '{', even if not offside @@ -1318,7 +1366,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, if debug then dprintf "RPAREN/RBRACE/BAR_RBRACE/RBRACK/BAR_RBRACK/RQUOTE/END at %a terminates CtxtParen()\n" outputPos tokenStartPos popCtxt() // Queue a dummy token at this position to check if any closing rules apply - delayToken(tokenTup.UseLocation(ODUMMY token)) + delayToken(pool.UseLocation(tokenTup, ODUMMY token)) returnToken tokenLexbufState token // Balancing rule. Encountering a 'end' can balance with a 'with' but only when not offside @@ -1326,7 +1374,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, when not (tokenStartCol + 1 <= offsidePos.Column) -> if debug then dprintf "END at %a terminates CtxtWithAsAugment()\n" outputPos tokenStartPos popCtxt() - delayToken(tokenTup.UseLocation(ODUMMY token)) // make sure we queue a dummy token at this position to check if any closing rules apply + delayToken(pool.UseLocation(tokenTup, ODUMMY token)) // make sure we queue a dummy token at this position to check if any closing rules apply returnToken tokenLexbufState OEND // Transition rule. CtxtNamespaceHead ~~~> CtxtSeqBlock @@ -1698,6 +1746,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, insertComingSoonTokens("MODULE", MODULE_COMING_SOON, MODULE_IS_HERE) if debug then dprintf "MODULE: entering CtxtModuleHead, awaiting EQUALS to go to CtxtSeqBlock (%a)\n" outputPos tokenStartPos pushCtxt tokenTup (CtxtModuleHead (tokenStartPos, token)) + pool.Return tokenTup hwTokenFetch useBlockRule // exception ... ~~~> CtxtException @@ -1746,7 +1795,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | Some tok -> popCtxt() if debug then dprintf "--> inserting %+A\n" tok - delayTokenNoProcessing (tokenTup.UseLocation tok) + delayTokenNoProcessing (pool.UseLocation(tokenTup, tok)) // for the rest, we silently pop them | _ -> popCtxt() popCtxt() // pop CtxtMemberBody @@ -2034,7 +2083,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, // if e1 then e2 // else if e3 then e4 // else if e5 then e6 - let _ = popNextTokenTup() + popNextTokenTup() |> pool.Return if debug then dprintf "ELSE IF: replacing ELSE IF with ELIF, pushing CtxtIf, CtxtVanilla(%a)\n" outputPos tokenStartPos pushCtxt tokenTup (CtxtIf tokenStartPos) returnToken tokenLexbufState ELIF @@ -2102,6 +2151,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, insertComingSoonTokens("TYPE", TYPE_COMING_SOON, TYPE_IS_HERE) if debug then dprintf "TYPE, pushing CtxtTypeDefns(%a)\n" outputPos tokenStartPos pushCtxt tokenTup (CtxtTypeDefns tokenStartPos) + pool.Return tokenTup hwTokenFetch useBlockRule | TRY, _ -> @@ -2120,6 +2170,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | ODUMMY(_), _ -> if debug then dprintf "skipping dummy token as no offside rules apply\n" + pool.Return tokenTup hwTokenFetch (useBlockRule) // Ordinary tokens start a vanilla block @@ -2142,32 +2193,35 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | Some LPAREN -> HIGH_PRECEDENCE_PAREN_APP | Some LBRACK -> HIGH_PRECEDENCE_BRACK_APP | _ -> failwith "unreachable" - delayToken(dotTokenTup.UseLocation hpa) + delayToken(pool.UseLocation(dotTokenTup, hpa)) delayToken tokenTup true // Insert HIGH_PRECEDENCE_TYAPP if needed | (DELEGATE | IDENT _ | IEEE64 _ | IEEE32 _ | DECIMAL _ | INT8 _ | INT16 _ | INT32 _ | INT64 _ | NATIVEINT _ | UINT8 _ | UINT16 _ | UINT32 _ | UINT64 _ | BIGNUM _) when peekAdjacentTypars false tokenTup -> let lessTokenTup = popNextTokenTup() - delayToken (lessTokenTup.UseLocation(match lessTokenTup.Token with LESS _ -> LESS true | _ -> failwith "unreachable")) + delayToken (pool.UseLocation(lessTokenTup, match lessTokenTup.Token with LESS _ -> LESS true | _ -> failwith "unreachable")) if debug then dprintf "softwhite inserting HIGH_PRECEDENCE_TYAPP at dotTokenPos = %a\n" outputPos (startPosOfTokenTup lessTokenTup) - delayToken (lessTokenTup.UseLocation(HIGH_PRECEDENCE_TYAPP)) + delayToken (pool.UseLocation(lessTokenTup, HIGH_PRECEDENCE_TYAPP)) delayToken (tokenTup) + pool.Return lessTokenTup true // Split this token to allow "1..2" for range specification | INT32_DOT_DOT (i, v) -> let dotDotPos = new LexbufState(tokenTup.EndPos.ShiftColumnBy(-2), tokenTup.EndPos, false) - delayToken(new TokenTup(DOT_DOT, dotDotPos, tokenTup.LastTokenPos)) - delayToken(tokenTup.UseShiftedLocation(INT32(i, v), 0, -2)) + delayToken(let rented = pool.Rent() in rented.Token <- DOT_DOT; rented.LexbufState <- dotDotPos; rented.LastTokenPos <- tokenTup.LastTokenPos; rented) + delayToken(pool.UseShiftedLocation(tokenTup, INT32(i, v), 0, -2)) + pool.Return tokenTup true // Split @>. and @@>. into two | RQUOTE_DOT (s, raw) -> let dotPos = new LexbufState(tokenTup.EndPos.ShiftColumnBy(-1), tokenTup.EndPos, false) - delayToken(new TokenTup(DOT, dotPos, tokenTup.LastTokenPos)) - delayToken(tokenTup.UseShiftedLocation(RQUOTE(s, raw), 0, -1)) + delayToken(let rented = pool.Rent() in rented.Token <- DOT; rented.LexbufState <- dotPos; rented.LastTokenPos <- tokenTup.LastTokenPos; rented) + delayToken(pool.UseShiftedLocation(tokenTup, RQUOTE(s, raw), 0, -1)) + pool.Return tokenTup true | MINUS | PLUS_MINUS_OP _ | PERCENT_OP _ | AMP | AMP_AMP @@ -2176,7 +2230,7 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | PERCENT_OP s -> (s = "%") || (s = "%%") | _ -> true) && nextTokenIsAdjacent tokenTup && - not (prevWasAtomicEnd && (tokenTup.LastTokenPos.Y = startPosOfTokenTup tokenTup))) -> + not (prevWasAtomicEnd && (tokenTup.LastTokenPos = startPosOfTokenTup tokenTup))) -> let plus = match tokenTup.Token with @@ -2189,7 +2243,10 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | _ -> false let nextTokenTup = popNextTokenTup() /// Merge the location of the prefix token and the literal - let delayMergedToken tok = delayToken(new TokenTup(tok, new LexbufState(tokenTup.LexbufState.StartPos, nextTokenTup.LexbufState.EndPos, nextTokenTup.LexbufState.PastEOF), tokenTup.LastTokenPos)) + let delayMergedToken tok = + delayToken(let rented = pool.Rent() in rented.Token <- tok; rented.LexbufState <- new LexbufState(tokenTup.LexbufState.StartPos, nextTokenTup.LexbufState.EndPos, nextTokenTup.LexbufState.PastEOF); rented.LastTokenPos <- tokenTup.LastTokenPos; rented) + pool.Return nextTokenTup + pool.Return tokenTup let noMerge() = let tokenName = match tokenTup.Token with @@ -2201,7 +2258,8 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, | _ -> failwith "unreachable" let token = ADJACENT_PREFIX_OP tokenName delayToken nextTokenTup - delayToken (tokenTup.UseLocation token) + delayToken (pool.UseLocation(tokenTup, token)) + pool.Return tokenTup if plusOrMinus then match nextTokenTup.Token with @@ -2227,14 +2285,18 @@ type LexFilterImpl (lightSyntaxStatus: LightSyntaxStatus, compilingFsLib, lexer, and pushCtxtSeqBlockAt(p: TokenTup, addBlockBegin, addBlockEnd) = if addBlockBegin then if debug then dprintf "--> insert OBLOCKBEGIN \n" - delayToken(p.UseLocation OBLOCKBEGIN) + delayToken(pool.UseLocation(p, OBLOCKBEGIN)) pushCtxt p (CtxtSeqBlock(FirstInSeqBlock, startPosOfTokenTup p, addBlockEnd)) let rec swTokenFetch() = let tokenTup = popNextTokenTup() let tokenReplaced = rulesForBothSoftWhiteAndHardWhite tokenTup if tokenReplaced then swTokenFetch() - else returnToken tokenTup.LexbufState tokenTup.Token + else + let lexbufState = tokenTup.LexbufState + let tok = tokenTup.Token + pool.Return tokenTup + returnToken lexbufState tok //---------------------------------------------------------------------------- // Part VI. Publish the new lexer function. diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticLinkTests.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticLinkTests.fs new file mode 100644 index 0000000000000000000000000000000000000000..8d47ba7dd7e2cb2fb78699466e69a50235b7fb9b --- /dev/null +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticLinkTests.fs @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL + +open System.IO +open System.Reflection +open FSharp.Compiler.UnitTests +open NUnit.Framework + +[] +module StaticLinkTests = + + [] + let ``Static link simple library``() = + let module1 = + let source = + """ +module Module1 + +type C() = class end + """ + Compilation.Create(source, Fsx, Library) + + let module2 = + let source = + """ +let y = Module1.C() +printfn "%A" y + """ + Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp(module1, staticLink=true)]) + + CompilerAssert.Execute(module2, + beforeExecute=(fun _ deps -> + deps + |> List.iter (fun dep -> try File.Delete dep with | _ -> ()))) + + [] + let ``Simple exe should fail to execute if dependency was not found and is not statically linked``() = + let module1 = + let source = + """ +module Module1 + +type C() = class end + """ + Compilation.Create(source, Fsx, Library) + + let module2 = + let source = + """ +let y = Module1.C() +printfn "%A" y + """ + Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp module1]) + + Assert.Throws(fun _ -> + CompilerAssert.Execute(module2, + beforeExecute=(fun _ deps -> + deps + |> List.iter (fun dep -> try File.Delete dep with | _ -> ())))) |> ignore + + [] + let ``Simple exe should execute if dependency was found and is not statically linked``() = + let module1 = + let source = + """ +module Module1 + +type C() = class end + """ + Compilation.Create(source, Fsx, Library) + + let module2 = + let source = + """ +let y = Module1.C() +printfn "%A" y + """ + Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp module1]) + + CompilerAssert.Execute module2 + + [] + let ``Static link quotes in multiple modules``() = + let module1 = + let source = + """ +module Module1 + +module Test = + let inline run() = + <@ fun (output:'T[]) (input:'T[]) (length:int) -> + let start = 0 + let mutable i = start + while i < length do + output.[i] <- input.[i] + i <- i + 1 @> + + let bar() = + sprintf "%A" (run()) + +type C() = + + [] + static member F x = (C(), System.DateTime.Now) + """ + Compilation.Create(source, Fsx, Library) + + let module2 = + let source = + """ + +let a = Module1.Test.bar() +let b = sprintf "%A" (Module1.Test.run()) + +let test1 = (a=b) +type D() = + + [] + static member F x = (Module1.C(), D(), System.DateTime.Now) + + +let z2 = Quotations.Expr.TryGetReflectedDefinition(typeof.GetMethod("F")) +let s2 = (sprintf "%2000A" z2) +let test2 = (s2 = "Some Lambda (x, NewTuple (NewObject (C), PropertyGet (None, Now, [])))") + +let z3 = Quotations.Expr.TryGetReflectedDefinition(typeof.GetMethod("F")) +let s3 = (sprintf "%2000A" z3) +let test3 = (s3 = "Some Lambda (x, NewTuple (NewObject (C), NewObject (D), PropertyGet (None, Now, [])))") + +#if EXTRAS +// Add some references to System.ValueTuple, and add a test case which statically links this DLL +let test4 = struct (3,4) +let test5 = struct (z2,z3) +#endif + +if not test1 then + stdout.WriteLine "*** test1 FAILED"; + eprintf "FAILED, in-module result %s is different from out-module call %s" a b + +if not test2 then + stdout.WriteLine "*** test2 FAILED"; + eprintf "FAILED, %s is different from expected" s2 +if not test3 then + stdout.WriteLine "*** test3 FAILED"; + eprintf "FAILED, %s is different from expected" s3 + + +if test1 && test2 && test3 then () +else failwith "Test Failed" + """ + Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp(module1, staticLink=true)]) + + CompilerAssert.Execute(module2, ignoreWarnings=true) + + [] + let ``Static link quotes in multiple modules - optimized``() = + let module1 = + let source = + """ +module Module1 + +module Test = + let inline run() = + <@ fun (output:'T[]) (input:'T[]) (length:int) -> + let start = 0 + let mutable i = start + while i < length do + output.[i] <- input.[i] + i <- i + 1 @> + + let bar() = + sprintf "%A" (run()) + +type C() = + + [] + static member F x = (C(), System.DateTime.Now) + """ + Compilation.Create(source, Fsx, Library, [|"--optimize+"|]) + + let module2 = + let source = + """ + +let a = Module1.Test.bar() +let b = sprintf "%A" (Module1.Test.run()) + +let test1 = (a=b) +type D() = + + [] + static member F x = (Module1.C(), D(), System.DateTime.Now) + + +let z2 = Quotations.Expr.TryGetReflectedDefinition(typeof.GetMethod("F")) +let s2 = (sprintf "%2000A" z2) +let test2 = (s2 = "Some Lambda (x, NewTuple (NewObject (C), PropertyGet (None, Now, [])))") + +let z3 = Quotations.Expr.TryGetReflectedDefinition(typeof.GetMethod("F")) +let s3 = (sprintf "%2000A" z3) +let test3 = (s3 = "Some Lambda (x, NewTuple (NewObject (C), NewObject (D), PropertyGet (None, Now, [])))") + +#if EXTRAS +// Add some references to System.ValueTuple, and add a test case which statically links this DLL +let test4 = struct (3,4) +let test5 = struct (z2,z3) +#endif + +if not test1 then + stdout.WriteLine "*** test1 FAILED"; + eprintf "FAILED, in-module result %s is different from out-module call %s" a b + +if not test2 then + stdout.WriteLine "*** test2 FAILED"; + eprintf "FAILED, %s is different from expected" s2 +if not test3 then + stdout.WriteLine "*** test3 FAILED"; + eprintf "FAILED, %s is different from expected" s3 + + +if test1 && test2 && test3 then () +else failwith "Test Failed" + """ + Compilation.Create(source, Fsx, Exe, [|"--optimize+"|], [CompilationReference.CreateFSharp(module1, staticLink=true)]) + + CompilerAssert.Execute(module2, ignoreWarnings=true) \ No newline at end of file diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 1c753cd25e0749906bd71220a62d31d042f22d08..11e886a055ddd81f2c7fa51241d1acbd52b628c5 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -namespace FSharp.Compiler.UnitTests +[] +module FSharp.Compiler.UnitTests.CompilerAssert open System open System.Diagnostics @@ -29,17 +30,54 @@ type ILVerifier (dllFilePath: string) = member this.VerifyILWithLineNumbers (qualifiedItemName: string, expectedIL: string) = ILChecker.checkILItemWithLineNumbers qualifiedItemName dllFilePath [ expectedIL ] -[] -module CompilerAssert = +type Worker () = + inherit MarshalByRefObject() - let checker = FSharpChecker.Create(suggestNamesForErrors=true) + member x.ExecuteTestCase assemblyPath (deps: string[]) = + AppDomain.CurrentDomain.add_AssemblyResolve(ResolveEventHandler(fun _ args -> + deps + |> Array.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = args.Name) + |> Option.bind (fun x -> if File.Exists x then Some x else None) + |> Option.map Assembly.LoadFile + |> Option.defaultValue null)) + let asm = Assembly.LoadFrom(assemblyPath) + let entryPoint = asm.EntryPoint + (entryPoint.Invoke(Unchecked.defaultof, [||])) |> ignore - let private config = TestFramework.initializeSuite () +type SourceKind = + | Fs + | Fsx + +type CompileOutput = + | Library + | Exe + +type CompilationReference = private CompilationReference of Compilation * staticLink: bool with + + static member CreateFSharp(cmpl: Compilation, ?staticLink) = + let staticLink = defaultArg staticLink false + CompilationReference(cmpl, staticLink) + +and Compilation = private Compilation of string * SourceKind * CompileOutput * options: string[] * CompilationReference list with + + static member Create(source, sourceKind, output, ?options, ?cmplRefs) = + let options = defaultArg options [||] + let cmplRefs = defaultArg cmplRefs [] + Compilation(source, sourceKind, output, options, cmplRefs) + +[] +type CompilerAssert private () = + + static let checker = FSharpChecker.Create(suggestNamesForErrors=true) + + static let config = TestFramework.initializeSuite () + + static let _ = config |> ignore // Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler #if !NETCOREAPP #else - let projectFile = """ + static let projectFile = """ @@ -56,13 +94,13 @@ module CompilerAssert = """ - let programFs = """ + static let programFs = """ open System [] let main argv = 0""" - let getNetCoreAppReferences = + static let getNetCoreAppReferences = let mutable output = "" let mutable errors = "" let mutable cleanUp = true @@ -107,37 +145,35 @@ let main argv = 0""" #endif #if FX_NO_APP_DOMAINS - let executeBuiltApp assembly = + static let executeBuiltApp assembly deps = let ctxt = AssemblyLoadContext("ContextName", true) try let asm = ctxt.LoadFromAssemblyPath(assembly) let entryPoint = asm.EntryPoint + ctxt.add_Resolving(fun ctxt name -> + deps + |> List.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = name.Name) + |> Option.map ctxt.LoadFromAssemblyPath + |> Option.defaultValue null) (entryPoint.Invoke(Unchecked.defaultof, [||])) |> ignore finally ctxt.Unload() #else - type Worker () = - inherit MarshalByRefObject() - - member __.ExecuteTestCase assemblyPath = - let asm = Assembly.LoadFrom(assemblyPath) - let entryPoint = asm.EntryPoint - (entryPoint.Invoke(Unchecked.defaultof, [||])) |> ignore - let pathToThisDll = Assembly.GetExecutingAssembly().CodeBase + static let pathToThisDll = Assembly.GetExecutingAssembly().CodeBase - let adSetup = + static let adSetup = let setup = new System.AppDomainSetup () setup.PrivateBinPath <- pathToThisDll setup - let executeBuiltApp assembly = + static let executeBuiltApp assembly deps = let ad = AppDomain.CreateDomain((Guid()).ToString(), null, adSetup) let worker = (ad.CreateInstanceFromAndUnwrap(pathToThisDll, typeof.FullName)) :?> Worker - worker.ExecuteTestCase assembly |>ignore + worker.ExecuteTestCase assembly (deps |> Array.ofList) |>ignore #endif - let private defaultProjectOptions = + static let defaultProjectOptions = { ProjectFileName = "Z:\\test.fsproj" ProjectId = None @@ -159,27 +195,146 @@ let main argv = 0""" Stamp = None } - let private gate = obj () - - let private compile isExe options source f = - lock gate <| fun () -> - let inputFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".fs") - let outputFilePath = Path.ChangeExtension (Path.GetTempFileName(), if isExe then ".exe" else ".dll") - try - File.WriteAllText (inputFilePath, source) - let args = - options - |> Array.append defaultProjectOptions.OtherOptions - |> Array.append [| "fsc.exe"; inputFilePath; "-o:" + outputFilePath; (if isExe then "--target:exe" else "--target:library"); "--nowin32manifest" |] - let errors, _ = checker.Compile args |> Async.RunSynchronously - - f (errors, outputFilePath) + static let rawCompile inputFilePath outputFilePath isExe options source = + File.WriteAllText (inputFilePath, source) + let args = + options + |> Array.append defaultProjectOptions.OtherOptions + |> Array.append [| "fsc.exe"; inputFilePath; "-o:" + outputFilePath; (if isExe then "--target:exe" else "--target:library"); "--nowin32manifest" |] + let errors, _ = checker.Compile args |> Async.RunSynchronously - finally - try File.Delete inputFilePath with | _ -> () - try File.Delete outputFilePath with | _ -> () + errors, outputFilePath - let Pass (source: string) = + static let compileAux isExe options source f : unit = + let inputFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".fs") + let outputFilePath = Path.ChangeExtension (Path.GetTempFileName(), if isExe then ".exe" else ".dll") + try + f (rawCompile inputFilePath outputFilePath isExe options source) + finally + try File.Delete inputFilePath with | _ -> () + try File.Delete outputFilePath with | _ -> () + + static let compileDisposable isScript isExe options source = + let ext = + if isScript then ".fsx" + else ".fs" + let inputFilePath = Path.ChangeExtension(Path.GetTempFileName(), ext) + let outputFilePath = Path.ChangeExtension (Path.GetTempFileName(), if isExe then ".exe" else ".dll") + let o = + { new IDisposable with + member _.Dispose() = + try File.Delete inputFilePath with | _ -> () + try File.Delete outputFilePath with | _ -> () } + try + o, rawCompile inputFilePath outputFilePath isExe options source + with + | _ -> + o.Dispose() + reraise() + + static let gate = obj () + + static let compile isExe options source f = + lock gate (fun _ -> compileAux isExe options source f) + + static let assertErrors ignoreWarnings (errors: FSharpErrorInfo[]) = + let errors = + if ignoreWarnings then + errors + |> Array.filter (fun error -> error.Severity <> FSharpErrorSeverity.Warning) + else + errors + if errors.Length > 0 then + Assert.Fail(sprintf "%A" errors) + + static let rec compileCompilationAux (disposals: ResizeArray) ignoreWarnings (cmpl: Compilation) : (FSharpErrorInfo[] * string) * string list = + let compilationRefs, deps = + match cmpl with + | Compilation(_, _, _, _, cmpls) -> + let compiledRefs = + cmpls + |> List.map (fun cmpl -> + match cmpl with + | CompilationReference (cmpl, staticLink) -> + compileCompilationAux disposals ignoreWarnings cmpl, staticLink) + + let compilationRefs = + compiledRefs + |> List.map (fun (((errors, outputFilePath), _), staticLink) -> + assertErrors ignoreWarnings errors + let rOption = "-r:" + outputFilePath + if staticLink then + [rOption;"--staticlink:" + Path.GetFileNameWithoutExtension outputFilePath] + else + [rOption]) + |> List.concat + |> Array.ofList + + let deps = + compiledRefs + |> List.map (fun ((_, deps), _) -> deps) + |> List.concat + |> List.distinct + + compilationRefs, deps + + let isScript = + match cmpl with + | Compilation(_, kind, _, _, _) -> + match kind with + | Fs -> false + | Fsx -> true + + let isExe = + match cmpl with + | Compilation(_, _, output, _, _) -> + match output with + | Library -> false + | Exe -> true + + let source = + match cmpl with + | Compilation(source, _, _, _, _) -> source + + let options = + match cmpl with + | Compilation(_, _, _, options, _) -> options + + let disposal, res = compileDisposable isScript isExe (Array.append options compilationRefs) source + disposals.Add disposal + + let deps2 = + compilationRefs + |> Array.filter (fun x -> not (x.Contains("--staticlink"))) + |> Array.map (fun x -> x.Replace("-r:", String.Empty)) + |> List.ofArray + + res, (deps @ deps2) + + static let rec compileCompilation ignoreWarnings (cmpl: Compilation) f = + let disposals = ResizeArray() + try + f (compileCompilationAux disposals ignoreWarnings cmpl) + finally + disposals + |> Seq.iter (fun x -> x.Dispose()) + + static member Compile(cmpl: Compilation, ?ignoreWarnings) = + let ignoreWarnings = defaultArg ignoreWarnings false + lock gate (fun () -> + compileCompilation ignoreWarnings cmpl (fun ((errors, _), _) -> + assertErrors ignoreWarnings errors)) + + static member Execute(cmpl: Compilation, ?ignoreWarnings, ?beforeExecute) = + let ignoreWarnings = defaultArg ignoreWarnings false + let beforeExecute = defaultArg beforeExecute (fun _ _ -> ()) + lock gate (fun () -> + compileCompilation ignoreWarnings cmpl (fun ((errors, outputFilePath), deps) -> + assertErrors ignoreWarnings errors + beforeExecute outputFilePath deps + executeBuiltApp outputFilePath deps)) + + static member Pass (source: string) = lock gate <| fun () -> let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously @@ -191,7 +346,7 @@ let main argv = 0""" Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - let TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = + static member TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = lock gate <| fun () -> let parseResults, fileAnswer = checker.ParseAndCheckFileInProject( @@ -222,30 +377,30 @@ let main argv = 0""" Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg") ) - let TypeCheckWithErrors (source: string) expectedTypeErrors = - TypeCheckWithErrorsAndOptions [||] source expectedTypeErrors + static member TypeCheckWithErrors (source: string) expectedTypeErrors = + CompilerAssert.TypeCheckWithErrorsAndOptions [||] source expectedTypeErrors - let TypeCheckSingleErrorWithOptions options (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = - TypeCheckWithErrorsAndOptions options source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + static member TypeCheckSingleErrorWithOptions options (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + CompilerAssert.TypeCheckWithErrorsAndOptions options source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] - let TypeCheckSingleError (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = - TypeCheckWithErrors source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + static member TypeCheckSingleError (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + CompilerAssert.TypeCheckWithErrors source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] - let CompileExe (source: string) = + static member CompileExe (source: string) = compile true [||] source (fun (errors, _) -> if errors.Length > 0 then Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)) - let CompileExeAndRun (source: string) = + static member CompileExeAndRun (source: string) = compile true [||] source (fun (errors, outputExe) -> if errors.Length > 0 then Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors) - executeBuiltApp outputExe + executeBuiltApp outputExe [] ) - let CompileLibraryAndVerifyILWithOptions options (source: string) (f: ILVerifier -> unit) = + static member CompileLibraryAndVerifyILWithOptions options (source: string) (f: ILVerifier -> unit) = compile false options source (fun (errors, outputFilePath) -> let errors = errors |> Array.filter (fun x -> x.Severity = FSharpErrorSeverity.Error) @@ -255,10 +410,10 @@ let main argv = 0""" f (ILVerifier outputFilePath) ) - let CompileLibraryAndVerifyIL (source: string) (f: ILVerifier -> unit) = - CompileLibraryAndVerifyILWithOptions [||] source f + static member CompileLibraryAndVerifyIL (source: string) (f: ILVerifier -> unit) = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [||] source f - let RunScript (source: string) (expectedErrorMessages: string list) = + static member RunScript (source: string) (expectedErrorMessages: string list) = lock gate <| fun () -> // Intialize output and input streams use inStream = new StringReader("") @@ -294,7 +449,7 @@ let main argv = 0""" Assert.AreEqual(expectedErrorMessage, errorMessage) ) - let ParseWithErrors (source: string) expectedParseErrors = + static member ParseWithErrors (source: string) expectedParseErrors = let sourceFileName = "test.fs" let parsingOptions = { FSharpParsingOptions.Default with SourceFiles = [| sourceFileName |] } let parseResults = checker.ParseFile(sourceFileName, SourceText.ofString source, parsingOptions) |> Async.RunSynchronously diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 563358e1a1fe276a6163abb841baac5fca7757a3..baec3523e1dabca8f255ef895aa922cb466116fb 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -34,6 +34,7 @@ + diff --git a/vsintegration/Vsix/RegisterFsharpPackage.pkgdef b/vsintegration/Vsix/RegisterFsharpPackage.pkgdef index c4a9de29e24964dfc24f3312dcd4b5541001be3f..3c029f496cf3f730dba8a97aa64e5ca5c4f52cd7 100644 --- a/vsintegration/Vsix/RegisterFsharpPackage.pkgdef +++ b/vsintegration/Vsix/RegisterFsharpPackage.pkgdef @@ -55,7 +55,7 @@ "1"="{92EF0900-2251-11D2-B72E-0000F87572EF}" [$RootKey$\Packages\{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}] -"ProductVersion"="10.4" +"ProductVersion"="{{FSProductVersion}}" "ProductName"="Visual F#" "CompanyName"="Microsoft Corp." diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj index 68b8b5e11222e88f89fb8b1ab171030f27db60e1..445549387746d4048ba0e12c51f6bb73db20dfc8 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj @@ -14,16 +14,22 @@ Designer - - Always - true - RegisterFsharpPackage.pkgdef - + + + RegisterFsharpPackage.pkgdef + {{FSProductVersion}} + $(FSProductVersion) + {{FSLanguageVersion}} + $(FSLanguageVersion) + true + + PreserveNewest License.txt true + PreserveNewest FSharp.Data.TypeProviders.dll diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj index 7779a1a3f0ebf9336df94ab95abf7d1b3b46f33e..8408b7a2989e7ae3b696790c9ea7367146284505 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj @@ -24,13 +24,22 @@ Menus.ctmenu Designer + + + true Microsoft.VisualStudio.FSharp.ProjectSystem.FSharpSR true VSPackage Designer + $(IntermediateOutputPath)resources\ + {{FSProductVersion}} + $(FSProductVersion) + {{FSLanguageVersion}} + $(FSLanguageVersion) + diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx b/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx index 0e636602e528bf7532ca2113bf923090034268e1..f29e74b9ecb9d937dae18926255854272bdbb445 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx @@ -464,10 +464,10 @@ Customizes the environment to maximize code editor screen space and improve the visibility of F# commands and tool windows. - Microsoft Visual F# Tools 10.4 for F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} 1.0 @@ -476,7 +476,7 @@ Microsoft Visual F# Tools - Visual F# Tools 10.4 for F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} F# Interactive diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.cs.xlf index e27841feae2d3c272072778a0a4334a2df608afc..f047f0cf58dc63a89c16083cccdcda2e1e990840 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.cs.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Nástroje Microsoft Visual F# 10.4 pro F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Nástroje Microsoft Visual F# {{FSProductVersion}} pro F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Nástroje Microsoft Visual F# 10.4 pro F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Nástroje Microsoft Visual F# {{FSProductVersion}} pro F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Nástroje Visual F# 10.4 pro F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Nástroje Visual F# {{FSProductVersion}} pro F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.de.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.de.xlf index 57e31224de593e794a01b76415e3f76914348ff9..cd550b54944c82d715ba786a2df3e418b217b910 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.de.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 für f# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} für f# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 für f# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} für f# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 für F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} für F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.es.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.es.xlf index 2ff3a9663bf3939f03d8ac17668546144a446a38..2204dcdc7d194431dfa189c4ff92a110a0d84c75 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.es.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Herramientas de Microsoft Visual F# 10.4 para F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Herramientas de Microsoft Visual F# {{FSProductVersion}} para F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Herramientas de Microsoft Visual F# 10.4 para F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Herramientas de Microsoft Visual F# {{FSProductVersion}} para F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 para F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} para F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.fr.xlf index 0e5d733739b6955d1734209e09e68715f8bfa278..a7bedb7cc556153a4581a2dac0d22b4346c883b4 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.fr.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 pour F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} pour F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 pour F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} pour F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 pour F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} pour F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.it.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.it.xlf index 6e93bc28a7436956839c7a8fbacd7c0c323e1c63..ba72bff02e0004d6f73e517cf7e2b8d1c150d0f6 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.it.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 per F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} per F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 per F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} per F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 per F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} per F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ja.xlf index e0c79c4a2bf769439845c9c5d3d75bb305ea3353..710b54d5b7007bbbc960014bb00fe156cedb4ff6 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ja.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - F# 4.6 用 Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}} 用 Microsoft Visual F# Tools {{FSProductVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - F# 4.6 用 Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}} 用 Microsoft Visual F# Tools {{FSProductVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - F# 4.6 用 Visual F# Tools 10.4 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}} 用 Visual F# Tools {{FSProductVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ko.xlf index 4133f5ea2933580f9ce8911d91ad3a34ba919ff1..588d5e014b96b22855340e2d983ca494ec9c1a68 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ko.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - F# 4.6용 Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}}용 Microsoft Visual F# Tools {{FSProductVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - F# 4.6용 Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}}용 Microsoft Visual F# Tools {{FSProductVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - F# 4.6용 Visual F# Tools 10.4 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}}용 Visual F# Tools {{FSProductVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pl.xlf index 5ae72d11dc855cdcba960210ba8190434eeb05bb..08a4b45dfb4d6e8d25204d4513cb042b2c6bdde3 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pl.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 dla języka F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} dla języka F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 dla języka F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} dla języka F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 dla języka F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} dla języka F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pt-BR.xlf index eb0221892adf2e2f9dfc2b6ff0e6f85bef7b7a2a..6ae72d28fde70e25f743725f106237545a85e676 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.pt-BR.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 para F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} para F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 para F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} para F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 para F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} para F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ru.xlf index 897d2db04fc96943fdbb6a9ab4e3440495ae683e..418494b459f853e6b8d20f8e1cd602ef99189e1d 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.ru.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 для F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} для F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 для F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} для F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 для F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} для F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.tr.xlf index b435f62c81706c3a0fdb16202d96fe787a582489..53643a6ae2a5af4694369292744757b52698786e 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.tr.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - F# 4.6 için Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}} için Microsoft Visual F# Tools {{FSProductVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - F# 4.6 için Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}} için Microsoft Visual F# Tools {{FSProductVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - F# 4.6 için Visual F# Araçları 10.4 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + F# {{FSLanguageVersion}} için Visual F# Araçları {{FSProductVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hans.xlf index 24e4048ae2ed0dfc33c73fc2387608f868b41ec1..4e3108b778fdca4274bda755d8041a7ba566a8f0 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hans.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 for F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - Microsoft Visual F# Tools 10.4 for F# 4.6 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - Visual F# Tools 10.4 for F# 4.6 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hant.xlf index 326a36bb8132c61ad111fbc12f715a133d8b70c9..7eb95bad0aa0c9b75fad66c74e54184c90c8bef2 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/xlf/VSPackage.zh-Hant.xlf @@ -433,13 +433,13 @@ - Microsoft Visual F# Tools 10.4 for F# 4.6 - 適用於 F# 4.6 的 Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + 適用於 F# {{FSLanguageVersion}} 的 Microsoft Visual F# Tools {{FSProductVersion}} - Microsoft Visual F# Tools 10.4 for F# 4.6 - 適用於 F# 4.6 的 Microsoft Visual F# Tools 10.4 + Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + 適用於 F# {{FSLanguageVersion}} 的 Microsoft Visual F# Tools {{FSProductVersion}} @@ -453,8 +453,8 @@ - Visual F# Tools 10.4 for F# 4.6 - 適用於 F# 4.6 的 Visual F# Tools 10.4 + Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}} + 適用於 F# {{FSLanguageVersion}} 的 Visual F# Tools {{FSProductVersion}}