From 522fc420f396393112b7ad8458f3881724837fb5 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 3 Jun 2019 13:17:04 -0700 Subject: [PATCH] Ensure that Language Version support flows to Parser (#6891) * update testing * Ensure Lange Feature can be used from the parser * remove comments on tests * repair tests.fs --- .../FSharp.Compiler.Service.fsproj | 6 + src/fsharp/CompileOps.fs | 91 +------- src/fsharp/CompileOps.fsi | 14 +- src/fsharp/CompileOptions.fs | 19 +- src/fsharp/FSComp.txt | 1 + src/fsharp/FSharp.Build/Fsc.fs | 2 +- .../FSharp.Compiler.Private.fsproj | 6 + src/fsharp/LanguageFeatures.fs | 90 ++++++++ src/fsharp/LanguageFeatures.fsi | 31 +++ src/fsharp/UnicodeLexing.fs | 21 +- src/fsharp/UnicodeLexing.fsi | 9 +- src/fsharp/ast.fs | 38 +++- src/fsharp/fsi/fsi.fs | 31 +-- src/fsharp/lex.fsl | 13 +- src/fsharp/pars.fsy | 20 +- src/fsharp/service/ServiceLexing.fs | 11 +- src/fsharp/service/service.fs | 14 +- src/fsharp/xlf/FSComp.txt.cs.xlf | 5 + src/fsharp/xlf/FSComp.txt.de.xlf | 5 + src/fsharp/xlf/FSComp.txt.es.xlf | 5 + src/fsharp/xlf/FSComp.txt.fr.xlf | 5 + src/fsharp/xlf/FSComp.txt.it.xlf | 5 + src/fsharp/xlf/FSComp.txt.ja.xlf | 5 + src/fsharp/xlf/FSComp.txt.ko.xlf | 5 + src/fsharp/xlf/FSComp.txt.pl.xlf | 5 + src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 5 + src/fsharp/xlf/FSComp.txt.ru.xlf | 5 + src/fsharp/xlf/FSComp.txt.tr.xlf | 5 + src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 5 + src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 5 + src/utils/CompilerLocationUtils.fs | 1 - src/utils/prim-lexing.fs | 49 ++-- src/utils/prim-lexing.fsi | 23 +- .../HashIfExpression.fs | 5 +- tests/fsharp/FSharpSuite.Tests.fsproj | 1 + tests/fsharp/HandleExpects.fs | 196 ++++++++++++++++ tests/fsharp/core/members/basics/test.fs | 214 +++++++++--------- .../members/self-identifier/version46/test.fs | 62 +++++ .../members/self-identifier/version47/test.fs | 58 +++++ tests/fsharp/single-test.fs | 69 ++++-- tests/fsharp/test-framework.fs | 3 +- tests/fsharp/tests.fs | 13 +- 42 files changed, 843 insertions(+), 333 deletions(-) create mode 100644 src/fsharp/LanguageFeatures.fs create mode 100644 src/fsharp/LanguageFeatures.fsi create mode 100644 tests/fsharp/HandleExpects.fs create mode 100644 tests/fsharp/core/members/self-identifier/version46/test.fs create mode 100644 tests/fsharp/core/members/self-identifier/version47/test.fs diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 158dd62bfaa..6bd595e6827 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -78,6 +78,12 @@ ErrorText/sr.fs + + Driver\LanguageFeatures.fsi + + + Driver\LanguageFeatures.fs + LexYaccRuntime/prim-lexing.fsi diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 72332359d6d..5d6e97782cb 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -28,6 +28,7 @@ open FSharp.Compiler.AttributeChecking open FSharp.Compiler.ConstraintSolver open FSharp.Compiler.DiagnosticMessage open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Import open FSharp.Compiler.Infos open FSharp.Compiler.Lexhelp @@ -1735,7 +1736,7 @@ let CollectDiagnostic (implicitIncludeDir, showFullPaths, flattenErrors, errorSt let os = System.Text.StringBuilder() OutputPhasedDiagnostic os err flattenErrors suggestNames errors.Add( Diagnostic.Short(isError, os.ToString()) ) - + relatedErrors |> List.iter OutputRelatedError match err with @@ -1834,82 +1835,6 @@ let ComputeMakePathAbsolute implicitIncludeDir (path: string) = with :? System.ArgumentException -> path - -//------------------------------------------------------------------------------------------------------------------ -// Language version command line switch -//------------------------------------------------------------------------------------------------------------------ -// Add your features to this List - in code use languageVersion.SupportsFeature(LanguageFeatures.yourFeature) -// a return value of false means your feature is not supported by the user's language selection -// All new language features added from now on must be protected by this. -// Note: -// * The fslang design process will require a decision about feature name and whether it is required. -// * When a feature is assigned a release language, we will scrub the code of feature references and apply -// the Release Language version. - -/// LanguageFeature enumeration -[] -type LanguageFeature = - | LanguageVersion46 = 0 - | LanguageVersion47 = 1 - | Nullness = 1000 - | ScriptingPackageManagement = 1001 - -/// LanguageVersion management -type LanguageVersion (specifiedVersion) = - - // When we increment language versions here preview is higher than current RTM version - static let languageVersion46 = 4.6m - static let languageVersion47 = 4.7m - - static let previewVersion = languageVersion47 // Language version when preview specified - static let defaultVersion = languageVersion46 // Language version when default specified - static let latestVersion = defaultVersion // Language version when latest specified - static let latestMajorVersion = languageVersion46 // Language version when latestmajor specified - - static let validOptions = [| "preview"; "default"; "latest"; "latestmajor" |] - static let languageVersions = set [| latestVersion |] - - static let features = dict [| - // Add new LanguageVersions here ... - LanguageFeature.LanguageVersion47, 4.7m - LanguageFeature.LanguageVersion46, 4.6m - LanguageFeature.Nullness, previewVersion - LanguageFeature.ScriptingPackageManagement, previewVersion - // Add new LanguageFeatures here ... - |] - - static let dumpAllowedValues () = - printfn "%s" (FSComp.SR.optsSupportedLangVersions()) - for v in validOptions do printfn "%s" v - for v in languageVersions |> Seq.sort do - let label = if v = defaultVersion || v = latestVersion then "(Default)" else "" - printf "%M %s" v label - exit 0 - 0m - - let specified = - match specifiedVersion with - | "?" -> dumpAllowedValues() - | "preview" -> previewVersion - | "default" -> latestVersion - | "latest" -> latestVersion - | "latestmajor" -> latestMajorVersion - | _ -> - let raiseError () = error(Error(FSComp.SR.optsUnrecognizedLanguageVersion specifiedVersion, rangeCmdArgs)) - match Decimal.TryParse(specifiedVersion) with - | true, v -> - if languageVersions.Contains(v) then v - else raiseError (); 0m - | _ -> - raiseError () - 0m - - /// Check if this feature is supported by the selected langversion - member __.SupportsFeature featureId = - match features.TryGetValue featureId with - | true, v -> v <= specified - | false, _ -> false - //---------------------------------------------------------------------------- // Configuration //---------------------------------------------------------------------------- @@ -3556,8 +3481,8 @@ let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompil if List.exists (Filename.checkSuffix lower) (FSharpSigFileSuffixes@FSharpImplFileSuffixes) then if not(FileSystem.SafeExists filename) then error(Error(FSComp.SR.buildCouldNotFindSourceFile filename, rangeStartup)) - // bug 3155: if the file name is indirect, use a full path - let lexbuf = UnicodeLexing.UnicodeFileAsLexbuf(filename, tcConfig.inputCodePage, retryLocked) + let isFeatureSupported featureId = tcConfig.langVersion.SupportsFeature featureId + let lexbuf = UnicodeLexing.UnicodeFileAsLexbuf(isFeatureSupported, filename, tcConfig.inputCodePage, retryLocked) ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) else error(Error(FSComp.SR.buildInvalidSourceFileExtension(SanitizeFileName filename tcConfig.implicitIncludeDir), rangeStartup)) with e -> (* errorR(Failure("parse failed")); *) errorRecovery e rangeStartup; None @@ -5080,11 +5005,13 @@ module private ScriptPreprocessClosure = | CodeContext.CompilationAndEvaluation -> ["INTERACTIVE"] | CodeContext.Compilation -> ["COMPILED"] | CodeContext.Editing -> "EDITING" :: (if IsScript filename then ["INTERACTIVE"] else ["COMPILED"]) - let lexbuf = UnicodeLexing.SourceTextAsLexbuf(sourceText) - + + let isFeatureSupported featureId = tcConfig.langVersion.SupportsFeature featureId + let lexbuf = UnicodeLexing.SourceTextAsLexbuf(isFeatureSupported, sourceText) + let isLastCompiland = (IsScript filename), tcConfig.target.IsExe // The root compiland is last in the list of compilands. ParseOneInputLexbuf (tcConfig, lexResourceManager, defines, lexbuf, filename, isLastCompiland, errorLogger) - + /// Create a TcConfig for load closure starting from a single .fsx file let CreateScriptTextTcConfig (legacyReferenceResolver, defaultFSharpBinariesDir, diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 1ebdab9a2a7..51bcc2dc2a6 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -16,6 +16,7 @@ open FSharp.Compiler.TypeChecker open FSharp.Compiler.Range open FSharp.Compiler.Ast open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Tast open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text @@ -217,19 +218,6 @@ type ICompilationThread = /// Enqueue work to be done on a compilation thread. abstract EnqueueWork: (CompilationThreadToken -> unit) -> unit -/// LanguageFeature enumeration -[] -type LanguageFeature = - | LanguageVersion46 = 0 - | LanguageVersion47 = 1 - | Nullness = 1000 - | ScriptingPackageManagement = 1001 - -/// LanguageVersion management -type LanguageVersion = - new: string -> LanguageVersion - member SupportsFeature: LanguageFeature-> bool - [] type CompilerTarget = | WinExe diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index a342275c475..d107c3f3949 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -17,6 +17,7 @@ open FSharp.Compiler.TcGlobals open FSharp.Compiler.Tast open FSharp.Compiler.Tastops open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Lib open FSharp.Compiler.Range open FSharp.Compiler.IlxGen @@ -813,13 +814,27 @@ let codeGenerationFlags isFsi (tcConfigB: TcConfigBuilder) = //---------------------- let defineSymbol tcConfigB s = tcConfigB.conditionalCompilationDefines <- s :: tcConfigB.conditionalCompilationDefines - + let mlCompatibilityFlag (tcConfigB: TcConfigBuilder) = CompilerOption ("mlcompatibility", tagNone, OptionUnit (fun () -> tcConfigB.mlCompatibility<-true; tcConfigB.TurnWarningOff(rangeCmdArgs, "62")), None, Some (FSComp.SR.optsMlcompatibility())) +/// LanguageVersion management +let setLanguageVersion (specifiedVersion) = + + let languageVersion = new LanguageVersion(specifiedVersion) + let dumpAllowedValues () = + printfn "%s" (FSComp.SR.optsSupportedLangVersions()) + for v in languageVersion.ValidOptions do printfn "%s" v + for v in languageVersion.ValidVersions do printfn "%s" v + exit 0 + + if specifiedVersion = "?" then dumpAllowedValues () + if not (languageVersion.ContainsVersion specifiedVersion) then error(Error(FSComp.SR.optsUnrecognizedLanguageVersion specifiedVersion, rangeCmdArgs)) + languageVersion + let languageFlags tcConfigB = [ // -langversion:? Display the allowed values for language version @@ -828,7 +843,7 @@ let languageFlags tcConfigB = // 'latest' (latest version, including minor versions), // 'preview' (features for preview) // or specific versions like '4.7' - CompilerOption("langversion", tagLangVersionValues, OptionString (fun switch -> tcConfigB.langVersion <- LanguageVersion(switch)), None, Some (FSComp.SR.optsLangVersion())) + CompilerOption("langversion", tagLangVersionValues, OptionString (fun switch -> tcConfigB.langVersion <- setLanguageVersion(switch)), None, Some (FSComp.SR.optsLangVersion())) CompilerOption("checked", tagNone, OptionSwitch (fun switch -> tcConfigB.checkOverflow <- (switch = OptionSwitch.On)), None, Some (FSComp.SR.optsChecked())) CompilerOption("define", tagString, OptionString (defineSymbol tcConfigB), None, Some (FSComp.SR.optsDefine())) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 4e0f034aac3..a324cc9ed4a 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -421,6 +421,7 @@ parsAttributesMustComeBeforeVal,"Attributes should be placed before 'val'" 568,parsAllEnumFieldsRequireValues,"All enum fields must be given values" 569,parsInlineAssemblyCannotHaveVisibilityDeclarations,"Accessibility modifiers are not permitted on inline assembly code types" 571,parsUnexpectedIdentifier,"Unexpected identifier: '%s'" +10,parsUnexpectedSymbolDot,"Unexpected symbol '.' in member definition. Expected 'with', '=' or other token." 572,parsUnionCasesCannotHaveVisibilityDeclarations,"Accessibility modifiers are not permitted on union cases. Use 'type U = internal ...' or 'type U = private ...' to give an accessibility to the whole representation." 573,parsEnumFieldsCannotHaveVisibilityDeclarations,"Accessibility modifiers are not permitted on enumeration fields" parsConsiderUsingSeparateRecordType,"Consider using a separate record type instead" diff --git a/src/fsharp/FSharp.Build/Fsc.fs b/src/fsharp/FSharp.Build/Fsc.fs index 89e6a64db6d..4f1a702d5a5 100644 --- a/src/fsharp/FSharp.Build/Fsc.fs +++ b/src/fsharp/FSharp.Build/Fsc.fs @@ -108,7 +108,7 @@ type public Fsc () as this = for item in embeddedFiles do builder.AppendSwitchIfNotNull("--embed:", item.ItemSpec) builder.AppendSwitchIfNotNull("--sourcelink:", sourceLink) - builder.AppendSwitchIfNotNull("--langVersion:", langVersion) + builder.AppendSwitchIfNotNull("--langversion:", langVersion) // NoFramework if noFramework then builder.AppendSwitch("--noframework") diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 365e7809f4f..87b834d425e 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -86,6 +86,12 @@ ErrorText\sr.fs + + Driver\LanguageFeatures.fsi + + + Driver\LanguageFeatures.fs + LexYaccRuntime\prim-lexing.fsi diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs new file mode 100644 index 00000000000..15a30f6b614 --- /dev/null +++ b/src/fsharp/LanguageFeatures.fs @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Coordinating compiler operations - configuration, loading initial context, reporting errors etc. +module internal FSharp.Compiler.Features + +open System + +//------------------------------------------------------------------------------------------------------------------ +// Language version command line switch +//------------------------------------------------------------------------------------------------------------------ +// Add your features to this List - in code use languageVersion.SupportsFeature(LanguageFeatures.yourFeature) +// a return value of false means your feature is not supported by the user's language selection +// All new language features added from now on must be protected by this. +// Note: +// * The fslang design process will require a decision about feature name and whether it is required. +// * When a feature is assigned a release language, we will scrub the code of feature references and apply +// the Release Language version. + +/// LanguageFeature enumeration +[] +type LanguageFeature = + | LanguageVersion46 = 0 + | LanguageVersion47 = 1 + | SingleUnderscorePattern = 2 + | Nullness = 1000 + | ScriptingPackageManagement = 1001 + +/// LanguageVersion management +type LanguageVersion (specifiedVersion) = + + // When we increment language versions here preview is higher than current RTM version + static let languageVersion46 = 4.6m + static let languageVersion47 = 4.7m + + static let previewVersion = languageVersion47 // Language version when preview specified + static let defaultVersion = languageVersion46 // Language version when default specified + static let latestVersion = defaultVersion // Language version when latest specified + static let latestMajorVersion = languageVersion46 // Language version when latestmajor specified + + static let validOptions = [| "preview"; "default"; "latest"; "latestmajor" |] + static let languageVersions = set [| latestVersion |] + + static let features = dict [| + // Add new LanguageVersions here ... + LanguageFeature.LanguageVersion47, 4.7m + LanguageFeature.LanguageVersion46, 4.6m + LanguageFeature.Nullness, previewVersion + LanguageFeature.ScriptingPackageManagement, previewVersion + LanguageFeature.SingleUnderscorePattern, previewVersion + + // Add new LanguageFeatures here ... + |] + + let specified = + match specifiedVersion with + | "?" -> 0m + | "preview" -> previewVersion + | "default" -> latestVersion + | "latest" -> latestVersion + | "latestmajor" -> latestMajorVersion + | _ -> + match Decimal.TryParse(specifiedVersion) with + | true, v -> v + | _ -> 0m + + /// Check if this feature is supported by the selected langversion + member __.SupportsFeature featureId = + match features.TryGetValue featureId with + | true, v -> v <= specified + | false, _ -> false + + /// Does the languageVersion support this version string + member __.ContainsVersion version = + match version with + | "?" | "preview" | "default" | "latest" | "latestmajor" -> true + | _ -> + match Decimal.TryParse(specifiedVersion) with + | true, v -> languageVersions.Contains v + | _ -> false + + /// Get a list of valid strings for help text + member __.ValidOptions = validOptions + + /// Get a list of valid versions for help text + member __.ValidVersions = [| + for v in languageVersions |> Seq.sort do + let label = if v = defaultVersion || v = latestVersion then "(Default)" else "" + yield sprintf "%M %s" v label + |] + diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi new file mode 100644 index 00000000000..a43ac242768 --- /dev/null +++ b/src/fsharp/LanguageFeatures.fsi @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Coordinating compiler operations - configuration, loading initial context, reporting errors etc. +module internal FSharp.Compiler.Features + +/// LanguageFeature enumeration +[] +type LanguageFeature = + | LanguageVersion46 = 0 + | LanguageVersion47 = 1 + | SingleUnderscorePattern = 2 + | Nullness = 1000 + | ScriptingPackageManagement = 1001 + +/// LanguageVersion management +type LanguageVersion = + + /// Create a LanguageVersion management object + new: string -> LanguageVersion + + /// Get the list of valid versions + member ContainsVersion: string -> bool + + /// Does the specified LanguageVersion support the specified feature + member SupportsFeature: LanguageFeature -> bool + + /// Get the list of valid versions + member ValidVersions: string array + + /// Get the list of valid options + member ValidOptions: string array diff --git a/src/fsharp/UnicodeLexing.fs b/src/fsharp/UnicodeLexing.fs index ca2e5f19cee..d34092940e2 100644 --- a/src/fsharp/UnicodeLexing.fs +++ b/src/fsharp/UnicodeLexing.fs @@ -7,6 +7,7 @@ module internal FSharp.Compiler.UnicodeLexing // open FSharp.Compiler.AbstractIL.Internal.Library +open FSharp.Compiler.Features open Internal.Utilities open System.IO @@ -14,15 +15,15 @@ open Internal.Utilities.Text.Lexing type Lexbuf = LexBuffer -let StringAsLexbuf (s:string) : Lexbuf = - LexBuffer<_>.FromChars (s.ToCharArray()) - -let FunctionAsLexbuf (bufferFiller: char[] * int * int -> int) : Lexbuf = - LexBuffer<_>.FromFunction bufferFiller +let StringAsLexbuf (supportsFeature: Features.LanguageFeature -> bool, s:string) : Lexbuf = + LexBuffer<_>.FromChars (supportsFeature, s.ToCharArray()) + +let FunctionAsLexbuf (supportsFeature: Features.LanguageFeature -> bool, bufferFiller: char[] * int * int -> int) : Lexbuf = + LexBuffer<_>.FromFunction(supportsFeature, bufferFiller) + +let SourceTextAsLexbuf (supportsFeature: Features.LanguageFeature -> bool, sourceText) = + LexBuffer.FromSourceText(supportsFeature, sourceText) -let SourceTextAsLexbuf sourceText = - LexBuffer.FromSourceText(sourceText) - // The choice of 60 retries times 50 ms is not arbitrary. The NTFS FILETIME structure // uses 2 second resolution for LastWriteTime. We retry long enough to surpass this threshold // plus 1 second. Once past the threshold the incremental builder will be able to retry asynchronously based @@ -41,7 +42,7 @@ let numRetries = 60 /// we can't just return the LexBuffer object, since the file it wraps wouldn't /// get closed when we're finished with the LexBuffer. Hence we return the stream, /// the reader and the LexBuffer. The caller should dispose the first two when done. -let UnicodeFileAsLexbuf (filename,codePage : int option, retryLocked:bool) : Lexbuf = +let UnicodeFileAsLexbuf (supportsFeature: Features.LanguageFeature -> bool, filename, codePage: int option, retryLocked: bool): Lexbuf = // Retry multiple times since other processes may be writing to this file. let rec getSource retryNumber = try @@ -68,5 +69,5 @@ let UnicodeFileAsLexbuf (filename,codePage : int option, retryLocked:bool) : Le else reraise() let source = getSource 0 - let lexbuf = LexBuffer<_>.FromChars(source.ToCharArray()) + let lexbuf = LexBuffer<_>.FromChars(supportsFeature, source.ToCharArray()) lexbuf diff --git a/src/fsharp/UnicodeLexing.fsi b/src/fsharp/UnicodeLexing.fsi index 7c0f0fb68d5..2478c7f857b 100644 --- a/src/fsharp/UnicodeLexing.fsi +++ b/src/fsharp/UnicodeLexing.fsi @@ -2,12 +2,13 @@ module internal FSharp.Compiler.UnicodeLexing +open FSharp.Compiler.Features open FSharp.Compiler.Text open Microsoft.FSharp.Text open Internal.Utilities.Text.Lexing type Lexbuf = LexBuffer -val internal StringAsLexbuf : string -> Lexbuf -val public FunctionAsLexbuf : (char [] * int * int -> int) -> Lexbuf -val public UnicodeFileAsLexbuf :string * int option * (*retryLocked*) bool -> Lexbuf -val public SourceTextAsLexbuf : ISourceText -> Lexbuf +val internal StringAsLexbuf: (Features.LanguageFeature -> bool) * string -> Lexbuf +val public FunctionAsLexbuf: (Features.LanguageFeature -> bool) * (char [] * int * int -> int) -> Lexbuf +val public UnicodeFileAsLexbuf: (Features.LanguageFeature -> bool) * string * int option * (*retryLocked*) bool -> Lexbuf +val public SourceTextAsLexbuf: (Features.LanguageFeature -> bool) * ISourceText -> Lexbuf diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index 94f40226214..a6623e07c18 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -12,6 +12,7 @@ open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler open FSharp.Compiler.UnicodeLexing open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.PrettyNaming open FSharp.Compiler.Range @@ -1966,36 +1967,51 @@ let PushCurriedPatternsToExpr synArgNameGenerator wholem isMember pats rhs = expr spatsl, expr -/// Helper for parsing the inline IL fragments. +let internal internalParseAssemblyCodeInstructions s isFeatureSupported m = #if NO_INLINE_IL_PARSER -let ParseAssemblyCodeInstructions _s m = + ignore s + ignore isFeatureSupported + errorR(Error((193, "Inline IL not valid in a hosted environment"), m)) [| |] #else -let ParseAssemblyCodeInstructions s m = - try FSharp.Compiler.AbstractIL.Internal.AsciiParser.ilInstrs + try + FSharp.Compiler.AbstractIL.Internal.AsciiParser.ilInstrs FSharp.Compiler.AbstractIL.Internal.AsciiLexer.token - (UnicodeLexing.StringAsLexbuf s) + (UnicodeLexing.StringAsLexbuf(isFeatureSupported, s)) with RecoverableParseError -> - errorR(Error(FSComp.SR.astParseEmbeddedILError(), m)); [| |] + errorR(Error(FSComp.SR.astParseEmbeddedILError(), m)); [||] #endif +let ParseAssemblyCodeInstructions s m = + // Public API can not answer the isFeatureSupported questions, so here we support everything + let isFeatureSupported (_featureId:LanguageFeature) = true + internalParseAssemblyCodeInstructions s isFeatureSupported m + +let internal internalParseAssemblyCodeType s isFeatureSupported m = + ignore s + ignore isFeatureSupported -/// Helper for parsing the inline IL fragments. #if NO_INLINE_IL_PARSER -let ParseAssemblyCodeType _s m = errorR(Error((193, "Inline IL not valid in a hosted environment"), m)) IL.EcmaMscorlibILGlobals.typ_Object #else -let ParseAssemblyCodeType s m = - try FSharp.Compiler.AbstractIL.Internal.AsciiParser.ilType + let isFeatureSupported (_featureId:LanguageFeature) = true + try + FSharp.Compiler.AbstractIL.Internal.AsciiParser.ilType FSharp.Compiler.AbstractIL.Internal.AsciiLexer.token - (UnicodeLexing.StringAsLexbuf s) + (UnicodeLexing.StringAsLexbuf(isFeatureSupported, s)) with RecoverableParseError -> errorR(Error(FSComp.SR.astParseEmbeddedILTypeError(), m)); IL.EcmaMscorlibILGlobals.typ_Object #endif +/// Helper for parsing the inline IL fragments. +let ParseAssemblyCodeType s m = + // Public API can not answer the isFeatureSupported questions, so here we support everything + let isFeatureSupported (_featureId:LanguageFeature) = true + internalParseAssemblyCodeType s isFeatureSupported m + //------------------------------------------------------------------------ // AST constructors //------------------------------------------------------------------------ diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 7032d3a1ac6..5ddfe1cc186 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -34,6 +34,7 @@ open FSharp.Compiler.Ast open FSharp.Compiler.CompileOptions open FSharp.Compiler.CompileOps open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Infos open FSharp.Compiler.InfoReader open FSharp.Compiler.NameResolution @@ -1691,9 +1692,11 @@ type internal FsiStdinLexerProvider let initialLightSyntaxStatus = tcConfigB.light <> Some false LightSyntaxStatus (initialLightSyntaxStatus, false (* no warnings *)) + let isFeatureSupported featureId = tcConfigB.langVersion.SupportsFeature featureId + let LexbufFromLineReader (fsiStdinSyphon: FsiStdinSyphon) readf = - UnicodeLexing.FunctionAsLexbuf - (fun (buf: char[], start, len) -> + UnicodeLexing.FunctionAsLexbuf + (isFeatureSupported, (fun (buf: char[], start, len) -> //fprintf fsiConsoleOutput.Out "Calling ReadLine\n" let inputOption = try Some(readf()) with :? EndOfStreamException -> None inputOption |> Option.iter (fun t -> fsiStdinSyphon.Add (t + "\n")) @@ -1709,7 +1712,7 @@ type internal FsiStdinLexerProvider for i = 0 to ntrimmed-1 do buf.[i+start] <- input.[i] ntrimmed - ) + )) //---------------------------------------------------------------------------- // Reading stdin as a lex stream @@ -1730,6 +1733,7 @@ type internal FsiStdinLexerProvider let tokenizer = LexFilter.LexFilter(interactiveInputLightSyntaxStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) tokenizer + let isFeatureSupported featureId = tcConfigB.langVersion.SupportsFeature featureId // Create a new lexer to read stdin member __.CreateStdinLexer (errorLogger) = @@ -1748,12 +1752,12 @@ type internal FsiStdinLexerProvider // Create a new lexer to read an "included" script file member __.CreateIncludedScriptLexer (sourceFileName, errorLogger) = - let lexbuf = UnicodeLexing.UnicodeFileAsLexbuf(sourceFileName,tcConfigB.inputCodePage,(*retryLocked*)false) + let lexbuf = UnicodeLexing.UnicodeFileAsLexbuf(isFeatureSupported, sourceFileName, tcConfigB.inputCodePage, (*retryLocked*)false) CreateLexerForLexBuffer (sourceFileName, lexbuf, errorLogger) // Create a new lexer to read a string member this.CreateStringLexer (sourceFileName, source, errorLogger) = - let lexbuf = UnicodeLexing.StringAsLexbuf(source) + let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, source) CreateLexerForLexBuffer (sourceFileName, lexbuf, errorLogger) member __.ConsoleInput = fsiConsoleInput @@ -1813,6 +1817,7 @@ type internal FsiInteractionProcessor stopProcessingRecovery e range0 istate,CompletedWithReportedError e + let isFeatureSupported featureId = tcConfigB.langVersion.SupportsFeature featureId let rangeStdin = rangeN Lexhelp.stdinMockFilename 0 @@ -2037,11 +2042,7 @@ type internal FsiInteractionProcessor let parseExpression (tokenizer:LexFilter.LexFilter) = reusingLexbufForParsing tokenizer.LexBuffer (fun () -> Parser.typedSeqExprEOF tokenizer.Lexer tokenizer.LexBuffer) - -// let parseType (tokenizer:LexFilter.LexFilter) = -// reusingLexbufForParsing tokenizer.LexBuffer (fun () -> -// Parser.typEOF tokenizer.Lexer tokenizer.LexBuffer) - + let mainThreadProcessParsedExpression ctok errorLogger (expr, istate) = istate |> InteractiveCatch errorLogger (fun istate -> istate |> mainThreadProcessAction ctok (fun ctok _tcConfig istate -> @@ -2171,7 +2172,7 @@ type internal FsiInteractionProcessor #if FX_LCIDFROMCODEPAGE use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID #endif - let lexbuf = UnicodeLexing.StringAsLexbuf(sourceText) + let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, sourceText) let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, errorLogger) currState |> InteractiveCatch errorLogger (fun istate -> @@ -2190,7 +2191,7 @@ type internal FsiInteractionProcessor #if FX_LCIDFROMCODEPAGE use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID #endif - let lexbuf = UnicodeLexing.StringAsLexbuf(sourceText) + let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, sourceText) let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, errorLogger) currState |> InteractiveCatch errorLogger (fun istate -> @@ -2645,8 +2646,8 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i member x.FormatValue(obj:obj, objTy) = fsiDynamicCompiler.FormatValue(obj, objTy) - member x.EvalExpression(sourceText) = - + member x.EvalExpression(sourceText) = + // Explanation: When the user of the FsiInteractiveSession object calls this method, the // code is parsed, checked and evaluated on the calling thread. This means EvalExpression // is not safe to call concurrently. @@ -2655,7 +2656,7 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i fsiInteractionProcessor.EvalExpression(ctok, sourceText, dummyScriptFileName, errorLogger) |> commitResult - member x.EvalExpressionNonThrowing(sourceText) = + member x.EvalExpressionNonThrowing(sourceText) = // Explanation: When the user of the FsiInteractiveSession object calls this method, the // code is parsed, checked and evaluated on the calling thread. This means EvalExpression // is not safe to call concurrently. diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index b72b15e8e9a..58684e74654 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -23,6 +23,7 @@ open FSharp.Compiler open FSharp.Compiler.Range open FSharp.Compiler.Ast open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Parser open FSharp.Compiler.Lexhelp open FSharp.Compiler.Lib @@ -142,19 +143,17 @@ let tryAppendXmlDoc (buff:option) (s:string) = let shouldStartLine args lexbuf (m:range) err tok = if (m.StartColumn <> 0) then fail args lexbuf err tok else tok - + let shouldStartFile args lexbuf (m:range) err tok = if (m.StartColumn <> 0 || m.StartLine <> 1) then fail args lexbuf err tok else tok - -let evalIfDefExpression startPos args (lookup:string->bool) (lexed:string) = - let lexbuf = LexBuffer.FromChars (lexed.ToCharArray ()) + +let evalIfDefExpression startPos isFeatureSupported args (lookup:string->bool) (lexed:string) = + let lexbuf = LexBuffer.FromChars (isFeatureSupported, lexed.ToCharArray ()) lexbuf.StartPos <- startPos lexbuf.EndPos <- startPos let tokenStream = FSharp.Compiler.PPLexer.tokenstream args - let expr = FSharp.Compiler.PPParser.start tokenStream lexbuf - LexerIfdefEval lookup expr } @@ -608,7 +607,7 @@ rule token args skip = parse { let m = lexbuf.LexemeRange let lookup id = List.contains id args.defines let lexed = lexeme lexbuf - let isTrue = evalIfDefExpression lexbuf.StartPos args lookup lexed + let isTrue = evalIfDefExpression lexbuf.StartPos lexbuf.SupportsFeature args lookup lexed args.ifdefStack := (IfDefIf,m) :: !(args.ifdefStack) // Get the token; make sure it starts at zero position & return diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 03c8902b3ee..d95f8ce5ce6 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -18,6 +18,7 @@ open FSharp.Compiler.Ast open FSharp.Compiler.Lib open FSharp.Compiler.PrettyNaming open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features #if DEBUG let debugPrint(s) = @@ -1911,9 +1912,12 @@ opt_typ: | /* EMPTY */ { None } | COLON typ { Some $2 } - atomicPatternLongIdent: - | UNDERSCORE DOT pathOp { let (LongIdentWithDots(lid,dotms)) = $3 in (None,LongIdentWithDots(ident("_",rhs parseState 1)::lid, rhs parseState 2::dotms)) } + | UNDERSCORE DOT pathOp { + if not (parseState.LexBuffer.SupportsFeature LanguageFeature.SingleUnderscorePattern) then + raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedSymbolDot()) + let (LongIdentWithDots(lid,dotms)) = $3 in (None,LongIdentWithDots(ident("_",rhs parseState 1)::lid, rhs parseState 2::dotms)) + } | GLOBAL DOT pathOp { let (LongIdentWithDots(lid,dotms)) = $3 in (None,LongIdentWithDots(ident(MangledGlobalName,rhs parseState 1) :: lid, rhs parseState 2 :: dotms)) } | pathOp { (None,$1) } | access pathOp { (Some($1), $2) } @@ -2105,7 +2109,7 @@ inlineAssemblyTyconRepr: | HASH stringOrKeywordString HASH { libraryOnlyError (lhs parseState) let lhsm = lhs parseState - SynTypeDefnSimpleRepr.LibraryOnlyILAssembly (ParseAssemblyCodeType $2 (rhs parseState 2),lhsm) } + SynTypeDefnSimpleRepr.LibraryOnlyILAssembly (internalParseAssemblyCodeType $2 parseState.LexBuffer.SupportsFeature (rhs parseState 2),lhsm) } classOrInterfaceOrStruct: | CLASS { TyconClass } @@ -4001,11 +4005,11 @@ inlineAssemblyExpr: | HASH stringOrKeywordString opt_inlineAssemblyTypeArg opt_curriedArgExprs opt_inlineAssemblyReturnTypes HASH { libraryOnlyWarning (lhs parseState) let s,sm = $2,rhs parseState 2 - (fun m -> SynExpr.LibraryOnlyILAssembly (ParseAssemblyCodeInstructions s sm,$3,List.rev $4,$5,m)) } - -opt_curriedArgExprs: - | opt_curriedArgExprs argExpr %prec expr_args - { $2 :: $1 } + (fun m -> SynExpr.LibraryOnlyILAssembly (internalParseAssemblyCodeInstructions s parseState.LexBuffer.SupportsFeature sm, $3, List.rev $4, $5, m)) } + +opt_curriedArgExprs: + | opt_curriedArgExprs argExpr %prec expr_args + { $2 :: $1 } | { [] } diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index a03c1deeffb..41e4b1c9e88 100644 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -15,6 +15,7 @@ open FSharp.Compiler.Parser open FSharp.Compiler.Range open FSharp.Compiler.Ast open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Lexhelp open FSharp.Compiler.Lib open Internal.Utilities @@ -767,18 +768,22 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, [] type FSharpSourceTokenizer(defineConstants: string list, filename: string option) = + + // Public callers are unable to answer LanguageVersion feature support questions. + // External Tools including the VS IDE will enable the default LanguageVersion + let isFeatureSupported (_featureId:LanguageFeature) = true + let lexResourceManager = new Lexhelp.LexResourceManager() let lexArgsLightOn = mkLexargs(filename, defineConstants, LightSyntaxStatus(true, false), lexResourceManager, ref [], DiscardErrorsLogger, PathMap.empty) let lexArgsLightOff = mkLexargs(filename, defineConstants, LightSyntaxStatus(false, false), lexResourceManager, ref [], DiscardErrorsLogger, PathMap.empty) member this.CreateLineTokenizer(lineText: string) = - let lexbuf = UnicodeLexing.StringAsLexbuf lineText + let lexbuf = UnicodeLexing.StringAsLexbuf(isFeatureSupported, lineText) FSharpLineTokenizer(lexbuf, Some lineText.Length, filename, lexArgsLightOn, lexArgsLightOff) - member this.CreateBufferTokenizer bufferFiller = - let lexbuf = UnicodeLexing.FunctionAsLexbuf bufferFiller + let lexbuf = UnicodeLexing.FunctionAsLexbuf(isFeatureSupported, bufferFiller) FSharpLineTokenizer(lexbuf, None, filename, lexArgsLightOn, lexArgsLightOff) module Keywords = diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index a3afd792b86..76d28cd3413 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -28,6 +28,7 @@ open FSharp.Compiler.CompileOps open FSharp.Compiler.CompileOptions open FSharp.Compiler.Driver open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Lib open FSharp.Compiler.PrettyNaming open FSharp.Compiler.Parser @@ -1533,8 +1534,11 @@ module internal Parser = let tokenizer = LexFilter.LexFilter(lightSyntaxStatus, options.CompilingFsLib, Lexer.token lexargs true, lexbuf) tokenizer.Lexer - let createLexbuf sourceText = - UnicodeLexing.SourceTextAsLexbuf(sourceText) + // Public callers are unable to answer LanguageVersion feature support questions. + // External Tools including the VS IDE will enable the default LanguageVersion + let isFeatureSupported (_featureId:LanguageFeature) = true + let createLexbuf sourceText isFeatureSupported = + UnicodeLexing.SourceTextAsLexbuf(isFeatureSupported, sourceText) let matchBraces(sourceText, fileName, options: FSharpParsingOptions, userOpName: string, suggestNamesForErrors: bool) = let delayedLogger = CapturingErrorLogger("matchBraces") @@ -1547,9 +1551,9 @@ module internal Parser = let delayedLogger = CapturingErrorLogger("matchBraces") use _unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> delayedLogger) use _unwindBP = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse - + let matchingBraces = new ResizeArray<_>() - Lexhelp.usingLexbufForParsing(createLexbuf sourceText, fileName) (fun lexbuf -> + Lexhelp.usingLexbufForParsing(createLexbuf sourceText isFeatureSupported, fileName) (fun lexbuf -> let errHandler = ErrorHandler(false, fileName, options.ErrorSeverityOptions, sourceText, suggestNamesForErrors) let lexfun = createLexerFunction fileName options lexbuf errHandler let parenTokensBalance t1 t2 = @@ -1585,7 +1589,7 @@ module internal Parser = use unwindBP = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse let parseResult = - Lexhelp.usingLexbufForParsing(createLexbuf sourceText, fileName) (fun lexbuf -> + Lexhelp.usingLexbufForParsing(createLexbuf sourceText isFeatureSupported, fileName) (fun lexbuf -> let lexfun = createLexerFunction fileName options lexbuf errHandler let isLastCompiland = fileName.Equals(options.LastFileName, StringComparison.CurrentCultureIgnoreCase) || diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 9abdabd61bb..1776d714871 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. Není definovaný obor názvů {0}. diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index e5f977192c6..ae21fdf349d 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. Der Namespace "{0}" ist nicht definiert. diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index e21d657eef8..4c6094fc077 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. El espacio de nombres "{0}" no está definido. diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index fd6cdbf5495..1798dcf68fe 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. L'espace de noms '{0}' n'est pas défini. diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index f60b7905f5d..1422a59d501 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. Lo spazio dei nomi '{0}' non è definito. diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 0c19a139941..6234ab500c8 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. 名前空間 '{0}' が定義されていません。 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 7185fb29359..8df70a67ea4 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. '{0}' 네임스페이스가 정의되지 않았습니다. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 340810b041a..48e5861b74a 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. Nie zdefiniowano przestrzeni nazw „{0}”. diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 597b93b0754..e94533db2fd 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. O namespace '{0}' não está definido. diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 7428d734b07..c877df99b27 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. Пространство имен "{0}" не определено. diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 1adde774d36..d9ecdae9d68 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. '{0}' ad alanı tanımlı değil. diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index a1741df6fc7..f4d2e63372e 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. 未定义命名空间“{0}”。 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 0cf2857c692..02dc6ef625b 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -22,6 +22,11 @@ Unrecognized value '{0}' for --langversion use --langversion:? for complete list + + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + + The namespace '{0}' is not defined. 未定義命名空間 '{0}'。 diff --git a/src/utils/CompilerLocationUtils.fs b/src/utils/CompilerLocationUtils.fs index da626b54c5e..95aa5c5a31e 100644 --- a/src/utils/CompilerLocationUtils.fs +++ b/src/utils/CompilerLocationUtils.fs @@ -207,7 +207,6 @@ module internal FSharpEnvironment = // For the prototype compiler, we can just use the current domain tryCurrentDomain() with e -> - System.Diagnostics.Debug.Assert(false, "Error while determining default location of F# compiler") None diff --git a/src/utils/prim-lexing.fs b/src/utils/prim-lexing.fs index fe71c121975..1f772d6e87e 100644 --- a/src/utils/prim-lexing.fs +++ b/src/utils/prim-lexing.fs @@ -50,12 +50,12 @@ type StringText(str: string) = lazy getLines str member __.String = str - + override __.GetHashCode() = str.GetHashCode() override __.Equals(obj: obj) = str.Equals(obj) interface ISourceText with - + member __.Item with get index = str.[index] member __.GetLastCharacterPosition() = @@ -106,6 +106,7 @@ namespace Internal.Utilities.Text.Lexing open FSharp.Compiler.Text open Microsoft.FSharp.Core open Microsoft.FSharp.Collections + open FSharp.Compiler.Features open System.Collections.Generic [] @@ -168,11 +169,11 @@ namespace Internal.Utilities.Text.Lexing 0, 0) - type internal LexBufferFiller<'Char> = (LexBuffer<'Char> -> unit) - + type internal LexBufferFiller<'Char> = (LexBuffer<'Char> -> unit) + and [] - internal LexBuffer<'Char>(filler: LexBufferFiller<'Char>) = - let context = new Dictionary(1) + internal LexBuffer<'Char>(filler: LexBufferFiller<'Char>, supportsFeature:LanguageFeature -> bool) = + let context = new Dictionary(1) let mutable buffer = [||] /// number of valid characters beyond bufferScanStart. let mutable bufferMaxScanLength = 0 @@ -195,8 +196,7 @@ namespace Internal.Utilities.Text.Lexing Array.blit keep 0 buffer 0 nkeep bufferScanStart <- 0 bufferMaxScanLength <- nkeep - - + member lexbuf.EndOfScan () : int = //Printf.eprintf "endOfScan, lexBuffer.lexemeLength = %d\n" lexBuffer.lexemeLength; if bufferAcceptAction < 0 then @@ -211,13 +211,12 @@ namespace Internal.Utilities.Text.Lexing member lexbuf.StartPos with get() = startPos and set b = startPos <- b - + member lexbuf.EndPos with get() = endPos and set b = endPos <- b member lexbuf.Lexeme = Array.sub buffer bufferScanStart lexemeLength - member lexbuf.BufferLocalStore = (context :> IDictionary<_,_>) member lexbuf.LexemeLength with get() : int = lexemeLength and set v = lexemeLength <- v member lexbuf.Buffer with get() : 'Char[] = buffer and set v = buffer <- v @@ -238,45 +237,46 @@ namespace Internal.Utilities.Text.Lexing member x.BufferScanPos = bufferScanStart + bufferScanLength member lexbuf.EnsureBufferSize n = - if lexbuf.BufferScanPos + n >= buffer.Length then - let repl = Array.zeroCreate (lexbuf.BufferScanPos + n) + if lexbuf.BufferScanPos + n >= buffer.Length then + let repl = Array.zeroCreate (lexbuf.BufferScanPos + n) Array.blit buffer bufferScanStart repl bufferScanStart bufferScanLength buffer <- repl + member __.SupportsFeature featureId = supportsFeature featureId - static member FromFunction (f : 'Char[] * int * int -> int) : LexBuffer<'Char> = + static member FromFunction (supportsFeature:LanguageFeature -> bool, f : 'Char[] * int * int -> int) : LexBuffer<'Char> = let extension= Array.zeroCreate 4096 let filler (lexBuffer: LexBuffer<'Char>) = let n = f (extension,0,extension.Length) lexBuffer.EnsureBufferSize n Array.blit extension 0 lexBuffer.Buffer lexBuffer.BufferScanPos n lexBuffer.BufferMaxScanLength <- lexBuffer.BufferScanLength + n - new LexBuffer<'Char>(filler) - + new LexBuffer<'Char>(filler, supportsFeature) + // Important: This method takes ownership of the array - static member FromArrayNoCopy (buffer: 'Char[]) : LexBuffer<'Char> = - let lexBuffer = new LexBuffer<'Char>(fun _ -> ()) + static member FromArrayNoCopy (supportsFeature:LanguageFeature -> bool, buffer: 'Char[]) : LexBuffer<'Char> = + let lexBuffer = new LexBuffer<'Char>((fun _ -> ()), supportsFeature) lexBuffer.Buffer <- buffer lexBuffer.BufferMaxScanLength <- buffer.Length lexBuffer // Important: this method does copy the array - static member FromArray (s: 'Char[]) : LexBuffer<'Char> = + static member FromArray (supportsFeature: LanguageFeature -> bool, s: 'Char[]) : LexBuffer<'Char> = let buffer = Array.copy s - LexBuffer<'Char>.FromArrayNoCopy buffer + LexBuffer<'Char>.FromArrayNoCopy(supportsFeature, buffer) // Important: This method takes ownership of the array - static member FromChars (arr:char[]) = LexBuffer.FromArrayNoCopy arr - - static member FromSourceText (sourceText: ISourceText) = + static member FromChars (supportsFeature:LanguageFeature -> bool, arr:char[]) = LexBuffer.FromArrayNoCopy (supportsFeature, arr) + + static member FromSourceText (supportsFeature: LanguageFeature -> bool, sourceText: ISourceText) = let mutable currentSourceIndex = 0 - LexBuffer.FromFunction(fun (chars, start, length) -> + LexBuffer.FromFunction(supportsFeature, fun (chars, start, length) -> let lengthToCopy = if currentSourceIndex + length <= sourceText.Length then length else sourceText.Length - currentSourceIndex - + if lengthToCopy <= 0 then 0 else sourceText.CopyTo(currentSourceIndex, chars, start, lengthToCopy) @@ -312,7 +312,6 @@ namespace Internal.Utilities.Text.Lexing open GenericImplFragments - [] type internal UnicodeTables(trans: uint16[] array, accept: uint16[]) = let sentinel = 255 * 256 + 255 diff --git a/src/utils/prim-lexing.fsi b/src/utils/prim-lexing.fsi index 4b4fd587171..bf9eb3171c1 100644 --- a/src/utils/prim-lexing.fsi +++ b/src/utils/prim-lexing.fsi @@ -39,6 +39,7 @@ open System.Collections.Generic open FSharp.Compiler.Text open Microsoft.FSharp.Core open Microsoft.FSharp.Control +open FSharp.Compiler.Features /// Position information stored for lexing tokens [] @@ -78,12 +79,12 @@ type internal Position = /// Apply a #line directive. member ApplyLineDirective : fileIdx:int * line:int -> Position - + /// Get an arbitrary position, with the empty string as filename. static member Empty : Position - + static member FirstLine : fileIdx:int -> Position - + [] /// Input buffers consumed by lexers generated by fslex.exe. /// The type must be generic to match the code generated by FsLex and FsYacc (if you would like to @@ -97,24 +98,28 @@ type internal LexBuffer<'Char> = /// The matched string. member Lexeme: 'Char [] - + /// Fast helper to turn the matched characters into a string, avoiding an intermediate array. static member LexemeString : LexBuffer -> string - + /// Dynamically typed, non-lexically scoped parameter table. member BufferLocalStore : IDictionary - + /// True if the refill of the buffer ever failed , or if explicitly set to True. member IsPastEndOfStream: bool with get,set + /// True if the refill of the buffer ever failed , or if explicitly set to True. + member SupportsFeature:LanguageFeature -> bool + /// Create a lex buffer suitable for Unicode lexing that reads characters from the given array. /// Important: does take ownership of the array. - static member FromChars: char[] -> LexBuffer + static member FromChars: (LanguageFeature -> bool) * char[] -> LexBuffer /// Create a lex buffer that reads character or byte inputs by using the given function. - static member FromFunction: ('Char[] * int * int -> int) -> LexBuffer<'Char> + static member FromFunction: (LanguageFeature -> bool) * ('Char[] * int * int -> int) -> LexBuffer<'Char> + /// Create a lex buffer backed by source text. - static member FromSourceText : ISourceText -> LexBuffer + static member FromSourceText : (LanguageFeature -> bool) * ISourceText -> LexBuffer /// The type of tables for an unicode lexer generated by fslex.exe. [] diff --git a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs index 91d7bfcb8d6..21667c727d5 100644 --- a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs +++ b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs @@ -12,7 +12,7 @@ open FSharp.Compiler open FSharp.Compiler.Lexer open FSharp.Compiler.Lexhelp open FSharp.Compiler.ErrorLogger -open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features open FSharp.Compiler.Ast open Internal.Utilities @@ -69,7 +69,8 @@ type HashIfExpression() = CompileThreadStatic.ErrorLogger <- errorLogger let parser (s : string) = - let lexbuf = LexBuffer.FromChars (s.ToCharArray ()) + let isFeatureSupported (_featureId:LanguageFeature) = true + let lexbuf = LexBuffer.FromChars (isFeatureSupported, s.ToCharArray ()) lexbuf.StartPos <- startPos lexbuf.EndPos <- startPos let tokenStream = PPLexer.tokenstream args diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 9376f62dcdf..20f62687ca2 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -27,6 +27,7 @@ NunitHelpers.fs + diff --git a/tests/fsharp/HandleExpects.fs b/tests/fsharp/HandleExpects.fs new file mode 100644 index 00000000000..9a11f90adc3 --- /dev/null +++ b/tests/fsharp/HandleExpects.fs @@ -0,0 +1,196 @@ +module HandleExpects + +open System +open System.IO +open System.Text.RegularExpressions +open System.Xml + +type Expects = { status:string; id:string; span:string; pattern:string; mutable matched:bool; line:string } +type ErrorMessage = { source:string; status:string; id:string; span:string; text:string; mutable matched:bool; line:string } +type Span = { startrow:int; startcol:int; endrow:int; endcol:int } + +let tryParseSpan (span:string) = + let s = span.Trim([| '('; ')' |]).Split(',') + match s.Length with + | 2 -> { startrow=Int32.Parse(s.[0]); startcol=Int32.Parse(s.[1]); endrow=Int32.MaxValue; endcol=Int32.MaxValue } + | 4 -> { startrow=Int32.Parse(s.[0]); startcol=Int32.Parse(s.[1]); endrow=Int32.Parse(s.[2]); endcol=Int32.Parse(s.[3]) } + | _ -> raise (InvalidDataException(sprintf "The span : '%s' is invalid" span)); + +let isStringEmpty s = String.IsNullOrWhiteSpace(s) +let isStringNotEmpty s = not (isStringEmpty s) +let stringToLower s = if isStringNotEmpty s then s.ToLower() else s +let areStringsEqual s1 s2 = String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase) = 0 +let areSpansEqual s1 s2 = + let span1 = tryParseSpan s1 + let span2 = tryParseSpan s2 + if span1.startrow <> span2.startrow then false + elif span1.startcol <> span2.startcol then false + elif span1.endrow <> span2.endrow then false + elif span1.endcol <> span2.endcol then false + else true + +let stripFromFileExpectations source = + let readExpect expect = + let pattern = "(?]*>{1})(?.*)(?)" //"().)*-->|<\w*((?!\/<).)*\/>|<(?\w+)[^>]*>(?>[^<]|(?R))*<\/\k\s*>)" + let rx = new Regex(pattern) + let matched = rx.Match(expect) + if matched.Success then + // The content of the Expects group contains a lot of invalid Xml and the Xml reader fails when it sees it. + // So we just save it away, remove it from the xml, then read the xml and put it back + // Save away the contents of the element and strip it out of expect pattern + let content = (matched.Groups.[2]).ToString() + let nocontentxpect = + if isStringEmpty content then expect + else expect.Replace(content, "") + + let rdr = XmlReader.Create(new StringReader(nocontentxpect)) + let mutable element = { status="success"; id = ""; span = ""; pattern = content; matched = false; line=nocontentxpect } + let mutable insideExpects = false + let mutable foundOne = false + try + let rec loop () = + if rdr.Read() then + match rdr.NodeType with + | XmlNodeType.Element when String.Compare(rdr.Name, "Expects", StringComparison.OrdinalIgnoreCase) = 0 -> + insideExpects <- true + if rdr.AttributeCount > 0 then + let status = stringToLower (rdr.GetAttribute("status")) + let span = rdr.GetAttribute("span") + let id = stringToLower (rdr.GetAttribute("id")) + element <- {element with status=status; id=id; span=span } + foundOne <- true + | XmlNodeType.EndElement when String.Compare(rdr.Name, "Expects", StringComparison.OrdinalIgnoreCase) = 0 -> + insideExpects <- false + | _ -> () + loop () + else () + loop () + if foundOne then Some element + else None + with | e -> printfn "Oops !!! %A" e; reraise() + else None + + File.ReadAllLines(source) + |> Array.filter(fun line -> line.Trim().StartsWith(@"//")) + |> Array.map(fun line -> line.Trim().Substring(2).Trim()) + |> Array.filter(fun line -> line.StartsWith(@" Array.map(fun expect -> readExpect expect) + |> Array.filter(fun expect -> expect.IsSome) + |> Array.map(fun expect -> expect.Value) + +let readErrorMessagesFromOutput output = + //Formats of error messages + // Syntax error in code: + // 1. filename(row,col): (sometext perhaps typecheck) error|warning ErrorNo: ErrorText + // e.g: Program.fs(5,9): error ErrorNo: ErrorText + // 2. Program.fs(5,3,5,20): (sometext perhaps typecheck) error FS0039: ErrorText + // e.g: + // Program.fs(5,3,5,20): (sometext perhaps typecheck) error FS0039: PicturePoint ... + // 3. error ErrorNo: ErrorText + // e.g: error FS0207: No inputs specified + let getErrorMessage line pattern = + let rx = new Regex(pattern) + let matched = rx.Match(line) + let getMatchForName (name:string) = matched.Groups.[name].ToString() + + if matched.Success then Some { + source = (getMatchForName "tagSourceFileName") + status = stringToLower (getMatchForName "tagStatus") + id = stringToLower (getMatchForName "tagErrorNo") + span = (getMatchForName "tagSpan") + text = (getMatchForName "tagText") + matched = false + line = line + } + else None + + let rgxTagSourceFileName = "(?[^(]{1,})(?:[(]{1})" + let rgxTagSpan = "(?[^):]{1,})(?:[)]{1})(?:[(\s:]*)" + let rgxTagStatus = "(?(error|typecheck error|warning|success|notin))" + let rgxColonWhiteSpace = "(?:[\s:]*)" + let rgxWhiteSpace = "(?:[\s]*)" + let rgxTagErrorNo = "(?\s*[^:\s]*)" + let rgxTagText = "(?.*)" + let rgxTagTail = "(?\s\[.*\]$)" + + // E.g: Q:\version46\test.fs(25,13): error FS0010: Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. [Q:\Temp\FSharp.Cambridge\vaw2t1vp.cai\f0bi0hny.wwx.fsproj] + let rgxFull = rgxTagSourceFileName + rgxTagSpan + rgxColonWhiteSpace + rgxTagStatus + rgxWhiteSpace + rgxTagErrorNo + rgxColonWhiteSpace + rgxTagText + rgxWhiteSpace + rgxTagTail + + // E.g: FSC : error FS0010: Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. [Q:\Temp\FSharp.Cambridge\vaw2t1vp.cai\f0bi0hny.wwx.fsproj] + let rgxShort = rgxTagStatus + rgxTagErrorNo + rgxColonWhiteSpace + rgxTagText + rgxWhiteSpace + rgxTagTail + [| + for line in output do + let errorMessage = + getErrorMessage line rgxFull + |> Option.orElse (getErrorMessage line rgxShort) + match errorMessage with + | Some e -> yield e + | _ -> () + |] + +let compareResults output (expectations:Expects array) (errorMessages:ErrorMessage array) = + for expect in expectations do + match expect.status with + | "error" + | "typecheck error" + | "warning" -> + // Check for this error/warning in found errors list + for msg in errorMessages do + let matched = + if isStringNotEmpty expect.id && not (areStringsEqual expect.id msg.id) then false + elif isStringNotEmpty expect.status && not (areStringsEqual expect.status msg.status) then false + elif isStringNotEmpty expect.span && not (areSpansEqual expect.span msg.span) then false + elif isStringNotEmpty expect.pattern then + let regex = new Regex(expect.pattern) + let matched = regex.Match(msg.text) + matched.Success + else true + if matched then + expect.matched <- true + msg.matched <- true + | "success" -> + // In this case search for text in the page + let regex = new Regex(expect.pattern) + for line in output do + let matched = regex.Match(line) + if matched.Success then expect.matched <- true + | "notin" -> + // In this case search for text not appearing in the page + let regex = new Regex(expect.pattern) + let mutable found = false + for line in output do + let matched = regex.Match(line) + if matched.Success then found <- true + if not found then expect.matched <- true + | _ -> () + +let verifyResults source outputPath = + let output = File.ReadAllLines(outputPath) + let expectations = stripFromFileExpectations source + if expectations.Length > 0 then + // There must be at least one to do this testing + let errorMessages = readErrorMessagesFromOutput output + compareResults output expectations errorMessages + + // Print out discovered expects + let verifiedexpectations = + expectations + |> Seq.fold(fun result expects -> + if not (expects.matched) then + printfn "Failed to match expected result '%s'" expects.line + false + else result + ) true + let verifiederrormessages = + errorMessages + |> Seq.fold(fun result msg -> + if not (msg.matched) then + printfn "Failed to match produced error message: '%s'" msg.line + false + else result + ) true + + if not (verifiedexpectations && verifiederrormessages) then + failwith (sprintf "Failed validating error codes") + +//HandleExpects.verifyResults @"C:\Users\kevinr\AppData\Local\Temp\FSharp.Cambridge\bcnyzkvb.ict\test.fs" @"C:\Users\kevinr\AppData\Local\Temp\FSharp.Cambridge\bcnyzkvb.ict\buildoutput.txt" \ No newline at end of file diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index ee04812f83f..27c9e6c3a40 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -54,8 +54,8 @@ open System.Windows.Forms //----------------------------------------- // Some simple object-expression tests -let x0 = { new System.Object() with member _.GetHashCode() = 3 } -let x1 = { new System.Windows.Forms.Form() with member _.GetHashCode() = 3 } +let x0 = { new System.Object() with member __.GetHashCode() = 3 } +let x1 = { new System.Windows.Forms.Form() with member __.GetHashCode() = 3 } //----------------------------------------- // Test defining an F# class @@ -72,16 +72,16 @@ type ClassType1 = abstract VirtualMethod2: string * string -> int abstract VirtualMethod1PostHoc: string -> int abstract VirtualMethod2PostHoc: string * string -> int - default _.VirtualMethod1(s) = 3 - default _.VirtualMethod2(s1,s2) = 3 + default x.VirtualMethod1(s) = 3 + default x.VirtualMethod2(s1,s2) = 3 new(s: string) = { inherit System.Object(); someField = "abc" } end type ClassType1 with - default _.VirtualMethod1PostHoc(s) = 3 - default _.VirtualMethod2PostHoc(s1,s2) = 3 + default x.VirtualMethod1PostHoc(s) = 3 + default x.VirtualMethod2PostHoc(s1,s2) = 3 new(s1,s2) = { inherit System.Object(); someField = "constructor2" + s1 + s2 } end @@ -93,11 +93,11 @@ type ClassType1 end -let x2 = { new ClassType1("a") with member _.GetHashCode() = 3 } -let x3 = { new ClassType1("a") with member _.VirtualMethod1(s) = 4 } +let x2 = { new ClassType1("a") with member __.GetHashCode() = 3 } +let x3 = { new ClassType1("a") with member __.VirtualMethod1(s) = 4 } let x4 = { new ClassType1("a") with - member _.VirtualMethod1(s) = 5 - member _.VirtualMethod2(s1,s2) = s1.Length + s2.Length } + member __.VirtualMethod1(s) = 5 + member __.VirtualMethod2(s1,s2) = s1.Length + s2.Length } @@ -119,18 +119,18 @@ type ClassType2 = inherit ClassType1 val someField2 : string - override _.VirtualMethod1(s) = 2001 + override x.VirtualMethod1(s) = 2001 override x.VirtualMethod2(s1,s2) = s1.Length + s2.Length + String.length x.someField2 new(s) = { inherit ClassType1(s); someField2 = s } end -let x22 = { new ClassType2("a") with member _.GetHashCode() = 3 } -let x32 = { new ClassType2("abc") with member _.VirtualMethod1(s) = 4002 } +let x22 = { new ClassType2("a") with member __.GetHashCode() = 3 } +let x32 = { new ClassType2("abc") with member __.VirtualMethod1(s) = 4002 } let x42 = { new ClassType2("abcd") with - member _.VirtualMethod1(s) = 5004 - member _.VirtualMethod2(s1,s2) = 500 + s1.Length + s2.Length } + member __.VirtualMethod1(s) = 5004 + member __.VirtualMethod2(s1,s2) = 500 + s1.Length + s2.Length } do test "e09wckj2ddwdw" (ignore(((x22 :> obj) :?> ClassType1)); true) do test "e09wckj2ddwdw" (ignore((x22 :> ClassType1)); true) @@ -166,7 +166,7 @@ module AbstractClassTest = begin type ClassType1 with interface IEnumerable with - member _.GetEnumerator() = failwith "no implementation" + member x.GetEnumerator() = failwith "no implementation" end end @@ -175,8 +175,8 @@ module AbstractClassTest = begin //let shouldGiveError2 = { new ClassType1("a") with AbstractMethod1(s) = 4 } //let shouldGiveError3a = new ClassType1("a") let x4 = { new ClassType1("a") with - member _.AbstractMethod1(s) = 5 - member _.AbstractMethod2(s1,s2) = s1.Length + s2.Length } + member __.AbstractMethod1(s) = 5 + member __.AbstractMethod2(s1,s2) = s1.Length + s2.Length } do test "e09wckj2d" (try ignore((x2 :> IEnumerable).GetEnumerator()); false with Failure "no implementation" -> true) @@ -191,18 +191,18 @@ module AbstractClassTest = begin inherit ClassType1 val someField2 : string - override _.AbstractMethod1(s) = 2001 + override x.AbstractMethod1(s) = 2001 override x.AbstractMethod2(s1,s2) = s1.Length + s2.Length + String.length x.someField2 new(s) = { inherit ClassType1(s); someField2 = s } end - let x22 = { new ClassType2("a") with member _.GetHashCode() = 3 } - let x32 = { new ClassType2("abc") with member _.AbstractMethod1(s) = 4002 } + let x22 = { new ClassType2("a") with member __.GetHashCode() = 3 } + let x32 = { new ClassType2("abc") with member __.AbstractMethod1(s) = 4002 } let x42 = { new ClassType2("abcd") with - member _.AbstractMethod1(s) = 5004 - member _.AbstractMethod2(s1,s2) = 500 + s1.Length + s2.Length } + member __.AbstractMethod1(s) = 5004 + member __.AbstractMethod2(s1,s2) = 500 + s1.Length + s2.Length } do test "e09wckj2ddwdw" (ignore(((x22 :> obj) :?> ClassType1)); true) do test "e09wckj2ddwdw" (ignore((x22 :> ClassType1)); true) @@ -218,7 +218,7 @@ module AbstractClassTest = begin inherit ClassType2 val someField3 : string - override _.AbstractMethod1(s) = 2001 + override x.AbstractMethod1(s) = 2001 override x.AbstractMethod2(s1,s2) = s1.Length + s2.Length + String.length x.someField2 + x.someField3.Length new(s) = { inherit ClassType2(s); someField3 = s } @@ -306,8 +306,8 @@ module RecordTypeTest = begin with get(idx) = x.instanceArray.[idx] member x.InstanceIndexer2 with get(idx1,idx2) = x.instanceArray2.[idx1].[idx2] - member _.InstanceIndexer2Count1 = 2 - member _.InstanceIndexer2Count2 = 2 + member x.InstanceIndexer2Count1 = 2 + member x.InstanceIndexer2Count2 = 2 member x.MutableInstanceIndexerCount = Array.length x.mutableInstanceArray @@ -318,8 +318,8 @@ module RecordTypeTest = begin member x.MutableInstanceIndexer2 with get (idx1,idx2) = x.mutableInstanceArray2.[idx1].[idx2] and set (idx1,idx2) (v:string) = x.mutableInstanceArray2.[idx1].[idx2] <- v - member _.MutableInstanceIndexer2Count1 = 2 - member _.MutableInstanceIndexer2Count2 = 2 + member x.MutableInstanceIndexer2Count1 = 2 + member x.MutableInstanceIndexer2Count2 = 2 static member StaticProperty = staticField static member MutableStaticProperty @@ -353,8 +353,8 @@ module RecordTypeTest = begin with get(idx) = x.instanceArray.[idx] member x.PrivateInstanceIndexer2 with get(idx1,idx2) = x.instanceArray2.[idx1].[idx2] - member _.PrivateInstanceIndexer2Count1 = 2 - member _.PrivateInstanceIndexer2Count2 = 2 + member x.PrivateInstanceIndexer2Count1 = 2 + member x.PrivateInstanceIndexer2Count2 = 2 member x.PrivateMutableInstanceIndexerCount = Array.length x.mutableInstanceArray @@ -365,8 +365,8 @@ module RecordTypeTest = begin member x.PrivateMutableInstanceIndexer2 with get (idx1,idx2) = x.mutableInstanceArray2.[idx1].[idx2] and set (idx1,idx2) (v:string) = x.mutableInstanceArray2.[idx1].[idx2] <- v - member _.PrivateMutableInstanceIndexer2Count1 = 2 - member _.PrivateMutableInstanceIndexer2Count2 = 2 + member x.PrivateMutableInstanceIndexer2Count1 = 2 + member x.PrivateMutableInstanceIndexer2Count2 = 2 static member PrivateStaticProperty = staticField static member PrivateMutableStaticProperty @@ -602,35 +602,35 @@ module UnionTypeTest = begin static member MutableStaticIndexerCount = Array.length mutableStaticArray // methods - member _.InstanceMethod(s1:string) = Printf.sprintf "InstanceMethod(%s)" s1 + member x.InstanceMethod(s1:string) = Printf.sprintf "InstanceMethod(%s)" s1 static member StaticMethod((s1:string),(s2:string)) = Printf.sprintf "AbstractType.StaticMethod(%s,%s)" s1 s2 // private versions of the above - member _.PrivateInstanceProperty = "InstanceProperty" - member _.PrivateMutableInstanceProperty + member x.PrivateInstanceProperty = "InstanceProperty" + member x.PrivateMutableInstanceProperty with get() = "a" and set(v:string) = Printf.printf "called mutator\n" - member _.PrivateInstanceIndexerCount = 1 + member x.PrivateInstanceIndexerCount = 1 - member _.PrivateInstanceIndexer + member x.PrivateInstanceIndexer with get(idx) = "b" - member _.PrivateInstanceIndexer2 + member x.PrivateInstanceIndexer2 with get(idx1,idx2) = "c" - member _.PrivateInstanceIndexer2Count1 = 1 - member _.PrivateInstanceIndexer2Count2 = 1 + member x.PrivateInstanceIndexer2Count1 = 1 + member x.PrivateInstanceIndexer2Count2 = 1 - member _.PrivateMutableInstanceIndexerCount = 3 + member x.PrivateMutableInstanceIndexerCount = 3 - member _.PrivateMutableInstanceIndexer + member x.PrivateMutableInstanceIndexer with get (idx1) = "a" and set (idx1) (v:string) = Printf.printf "called mutator\n" - member _.PrivateMutableInstanceIndexer2 + member x.PrivateMutableInstanceIndexer2 with get (idx1,idx2) = "a" and set (idx1,idx2) (v:string) = Printf.printf "called mutator\n" - member _.PrivateMutableInstanceIndexer2Count1 = 2 - member _.PrivateMutableInstanceIndexer2Count2 = 2 + member x.PrivateMutableInstanceIndexer2Count1 = 2 + member x.PrivateMutableInstanceIndexer2Count2 = 2 static member PrivateStaticProperty = staticField static member PrivateMutableStaticProperty @@ -649,7 +649,7 @@ module UnionTypeTest = begin static member PrivateMutableStaticIndexerCount = Array.length mutableStaticArray // methods - member _.PrivateInstanceMethod(s1:string) = Printf.sprintf "InstanceMethod(%s)" s1 + member x.PrivateInstanceMethod(s1:string) = Printf.sprintf "InstanceMethod(%s)" s1 static member PrivateStaticMethod((s1:string),(s2:string)) = Printf.sprintf "AbstractType.StaticMethod(%s,%s)" s1 s2 end @@ -1286,7 +1286,7 @@ open System.Windows.Forms type MyCanvas2 = class inherit Form - override _.OnPaint(args) = Printf.printf "OnPaint\n"; base.OnPaint(args) + override x.OnPaint(args) = Printf.printf "OnPaint\n"; base.OnPaint(args) new() = { inherit Form(); } end @@ -1443,10 +1443,10 @@ module MultiInterfaceTest = begin type C1 = class interface PrivateInterfaceA1 with - member _.M1() = () + member x.M1() = () end interface PrivateInterfaceA2 with - member _.M2() = () + member x.M2() = () end end end @@ -1458,10 +1458,10 @@ module MultiInterfaceTestNameConflict = begin type C1 = class interface PrivateInterfaceA1 with - member _.M() = () + member x.M() = () end interface PrivateInterfaceA2 with - member _.M() = () + member x.M() = () end end end @@ -1474,10 +1474,10 @@ module GenericMultiInterfaceTestNameConflict = begin type C1 = class interface PrivateInterfaceA1 with - member _.M(y) = y + member x.M(y) = y end interface PrivateInterfaceA2 with - member _.M(y) = y + member x.M(y) = y end end end @@ -1491,28 +1491,28 @@ module DeepInterfaceInheritance = begin type C1 = class interface InterfaceA2 with - member _.M1(y) = y - member _.M2(y) = y + y + member x.M1(y) = y + member x.M2(y) = y + y end new() = { inherit Object(); } end type C2 = class interface InterfaceA3 with - member _.M1(y) = y - member _.M2(y) = y + y - member _.M3(y) = y + y + y + member x.M1(y) = y + member x.M2(y) = y + y + member x.M3(y) = y + y + y end new() = { inherit Object(); } end type C3 = class interface InterfaceA2 with - member _.M1(y) = y - member _.M2(y) = y + y + member x.M1(y) = y + member x.M2(y) = y + y end interface InterfaceA3 with - member _.M3(y) = y + y + y + member x.M3(y) = y + y + y end new() = { inherit Object(); } end @@ -1542,28 +1542,28 @@ module DeepGenericInterfaceInheritance = begin type C1 = class interface InterfaceA2 with - member _.M1(y) = 1::y - member _.M2(x,y) = x::y + member obj.M1(y) = 1::y + member obj.M2(x,y) = x::y end new() = { inherit Object(); } end type C2 = class interface InterfaceA3 with - member _.M1(y) = "a" :: y - member _.M2(x,y) = x :: y - member _.M3(y) = "a" :: "b" :: "c" :: y + member obj.M1(y) = "a" :: y + member obj.M2(x,y) = x :: y + member obj.M3(y) = "a" :: "b" :: "c" :: y end new() = { inherit Object(); } end type C3 = class interface InterfaceA2 with - member _.M1(y) = "a" :: y - member _.M2(x,y) = x :: y + member obj.M1(y) = "a" :: y + member obj.M2(x,y) = x :: y end interface InterfaceA3 with - member _.M3(y) = "a" :: "b" :: "c" :: y + member obj.M3(y) = "a" :: "b" :: "c" :: y end new() = { inherit Object(); } end @@ -1892,12 +1892,12 @@ module Ralf = begin val PrecisionMean : float val Precision : float new (precisionMean, precision) = { PrecisionMean = 0.0; Precision = 0.0 } - override _.NumberOfDimensions() = 1 - override _.Density point = 1.0 - override _.AbsoluteDifference distribution = 0.0 - override _.Clone() = new Gaussian1D (0.0,0.0) :> Distribution + override x.NumberOfDimensions() = 1 + override x.Density point = 1.0 + override x.AbsoluteDifference distribution = 0.0 + override x.Clone() = new Gaussian1D (0.0,0.0) :> Distribution override x.CloneConstant() = new Gaussian1D (x.PrecisionMean,x.Precision) :> Distribution - override _.Sample numberOfSamples random = failwith "" // new Matrix (numberOfSamples,x.NumberOfDimensions) + override x.Sample numberOfSamples random = failwith "" // new Matrix (numberOfSamples,x.NumberOfDimensions) end end @@ -2015,19 +2015,19 @@ module PropertyOverrideTests = begin type CTest = class inherit A - override _.S1 with set v = () - override _.S2 with set s v = () - override _.S3 with set (s1,s2) v = () - override _.G1 with get () = 1.0 - override _.G2 with get (s:string) = 2.0 - override _.G3 with get (s1,s2) = 3.0 + override x.S1 with set v = () + override x.S2 with set s v = () + override x.S3 with set (s1,s2) v = () + override x.G1 with get () = 1.0 + override x.G2 with get (s:string) = 2.0 + override x.G3 with get (s1,s2) = 3.0 interface IA with - override _.S1 with set v = () - override _.S2 with set s v = () - override _.S3 with set (s1,s2) v = () - override _.G1 with get () = 1.0 - override _.G2 with get (s:string) = 2.0 - override _.G3 with get (s1,s2) = 3.0 + override x.S1 with set v = () + override x.S2 with set s v = () + override x.S3 with set (s1,s2) v = () + override x.G1 with get () = 1.0 + override x.G2 with get (s:string) = 2.0 + override x.G3 with get (s1,s2) = 3.0 end end @@ -2439,7 +2439,7 @@ module BaseCallTest = begin type C1 = class new() = {} abstract Blah : unit -> unit - default _.Blah () = + default this.Blah () = ignore <| printf "From C1\n"; res := !res + 2 end @@ -2447,7 +2447,7 @@ module BaseCallTest = begin type C2 = class inherit C1 new() = {inherit C1()} - override _.Blah() = + override this.Blah() = ignore <| printf "From C2\n"; res := !res + 1; base.Blah() @@ -2465,7 +2465,7 @@ module BaseCallTest2 = begin type C1 = class new() = {} abstract Blah : unit -> unit - default _.Blah () = + default this.Blah () = ignore <| printf "From C1b\n"; ignore <| printf "From C1b\n"; ignore <| printf "From C1b\n"; @@ -2478,7 +2478,7 @@ module BaseCallTest2 = begin type C2 = class inherit C1 new() = {inherit C1()} - override _.Blah() = + override this.Blah() = ignore <| printf "From C2b\n"; ignore <| printf "From C2b\n"; ignore <| printf "From C2b\n"; @@ -2492,7 +2492,7 @@ module BaseCallTest2 = begin type C3 = class inherit C2 new() = {inherit C2()} - override _.Blah() = + override this.Blah() = ignore <| printf "From C3c\n"; ignore <| printf "From C3c\n"; ignore <| printf "From C3c\n"; @@ -2559,7 +2559,7 @@ module SettingPropertiesInConstruction = begin val mutable q : int member x.Q with set v = x.q <- v abstract Foo : int -> int - default _.Foo(x) = x + default o.Foo(x) = x new() = { p = 0; q = 1 } end @@ -2728,7 +2728,7 @@ module StephenTolksdorfBug1112 = begin type Test() = class interface ITest2 with - member _.Foo<'t>(v:'t) : 't = v + member x.Foo<'t>(v:'t) : 't = v end end @@ -2751,7 +2751,7 @@ module Bug1281Test = begin val mutable key: int new (keyIn) = {key=keyIn} - member _.Item with get(i:int) = if i=0 then 1 else + member n.Item with get(i:int) = if i=0 then 1 else failwith "node has 2 items only" end let nd = new node (10) @@ -2772,11 +2772,11 @@ module Bug960Test1 = begin type C = class inherit B - override _.A + override x.A with get() = 3 and set(v : int) = (invalidArg "arg" "C.A.set" : unit) - override _.M() = 3 + override x.M() = 3 end end @@ -2804,7 +2804,7 @@ module Bug960Test2 = begin new() = { inherit B(3,4) } - override _.A + override x.A with get() = 3 and set(v : int) = (invalidArg "arg" "C.A.set" : unit) end end @@ -2815,19 +2815,19 @@ module RandomAdditionalNameResolutionTests = begin module M = begin type Foo() = class - member _.Name = "a" + member x.Name = "a" end type Foo<'a>() = class - member _.Name = "a" + member x.Name = "a" end type Goo<'a>() = class - member _.Name = "a" + member x.Name = "a" end type Goo() = class - member _.Name = "a" + member x.Name = "a" end end @@ -3103,9 +3103,9 @@ module CondensationTest = begin class [] - member _.Prop = "Hello" + member this.Prop = "Hello" [] - member _.Meth() = "Boo" + member this.Meth() = "Boo" end let getAttribute<'t> (memb: MemberInfo) = let attrib = memb.GetCustomAttributes(typeof<'t>, false) in @@ -3138,7 +3138,7 @@ module OptionalArgumentWithSubTyping = begin type Test(?bse: Base) = class let value = match bse with Some b -> b | _ -> new Base() - member _.Value = value + member t.Value = value end let t1 = new Test(bse=Base()) // should not trigger exception @@ -3254,7 +3254,7 @@ module NewConstraintUtilizedInTypeEstablishment_FSharp_1_0_4850 = begin type D() = class let f = 0 interface I with - member _.foo = f + 1 + member x.foo = f + 1 end end @@ -3264,8 +3264,8 @@ module TestTupleOverloadRules_Bug5985 = begin type C() = class - member _.CheckCooperativeLevel() = true - member _.CheckCooperativeLevel([] x:byref) = true + member device.CheckCooperativeLevel() = true + member device.CheckCooperativeLevel([] x:byref) = true end let c = C() diff --git a/tests/fsharp/core/members/self-identifier/version46/test.fs b/tests/fsharp/core/members/self-identifier/version46/test.fs new file mode 100644 index 00000000000..5a53a84a4cb --- /dev/null +++ b/tests/fsharp/core/members/self-identifier/version46/test.fs @@ -0,0 +1,62 @@ +//Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. +//Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. +//Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. +//Unexpected symbol '.' in member definition. Expected 'with', '=' or other token. + +module Global + +let failures = ref [] + +let report_failure (s : string) = + stderr.Write" NO: " + stderr.WriteLine s + failures := !failures @ [s] + +let test (s : string) b = + stderr.Write(s) + if b then stderr.WriteLine " OK" + else report_failure (s) + +let check s b1 b2 = test s (b1 = b2) + +//-------------------------------------------------------------- +// Test using "_" as the self identifier introduced in F# 4.7 +type MyTypeWithUnderscoreIdentifier () = + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + +[] +type MyStructWithUnderscoreIdentifier = + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + +type MyClassWithUnderscoreIdentifier () = + class + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + end + +type MyStructTypeWithUnderscoreIdentifier = + struct + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + end + + +#if TESTS_AS_APP +let RUN() = !failures +#else +let aa = + match !failures with + | [] -> + stdout.WriteLine "Test Passed" + System.IO.File.WriteAllText("test.ok","ok") + exit 0 + | _ -> + stdout.WriteLine "Test Failed" + exit 1 +#endif diff --git a/tests/fsharp/core/members/self-identifier/version47/test.fs b/tests/fsharp/core/members/self-identifier/version47/test.fs new file mode 100644 index 00000000000..99629250b65 --- /dev/null +++ b/tests/fsharp/core/members/self-identifier/version47/test.fs @@ -0,0 +1,58 @@ +module Global + +let failures = ref [] + +let report_failure (s : string) = + stderr.Write" NO: " + stderr.WriteLine s + failures := !failures @ [s] + +let test (s : string) b = + stderr.Write(s) + if b then stderr.WriteLine " OK" + else report_failure (s) + +let check s b1 b2 = test s (b1 = b2) + +//-------------------------------------------------------------- +// Test using "_" as the self identifier introduced in F# 4.7 +type MyTypeWithUnderscoreIdentifier () = + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + +[] +type MyStructWithUnderscoreIdentifier = + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + +type MyClassWithUnderscoreIdentifier () = + class + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + end + +type MyStructTypeWithUnderscoreIdentifier = + struct + member _.MethodWithUnderscoreSelf() = true + member __.MethodWithDoubleUnderscoreSelf() = true + member _E.MethodWithUnderscoreESelf() = true + end + + +#if TESTS_AS_APP +let RUN() = !failures +#else +let aa = + match !failures with + | [] -> + stdout.WriteLine "Test Passed" + System.IO.File.WriteAllText("test.ok","ok") + exit 0 + | _ -> + stdout.WriteLine "Test Failed" + exit 1 +#endif + diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index d3dc0f0c83e..0b481198079 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -5,15 +5,17 @@ open System.IO open System.Diagnostics open NUnit.Framework open TestFramework - +open HandleExpects type Permutation = | FSC_CORECLR + | FSC_CORECLR_BUILDONLY | FSI_CORECLR #if !FSHARP_SUITE_DRIVES_CORECLR_TESTS | FSI_FILE | FSI_STDIN | GENERATED_SIGNATURE + | FSC_BUILDONLY | FSC_OPT_MINUS_DEBUG | FSC_OPT_PLUS_DEBUG | AS_DLL @@ -59,7 +61,6 @@ type ProjectConfiguration = { Optimize:bool } - let replaceTokens tag (replacement:string) (template:string) = template.Replace(tag, replacement) let generateProps testCompilerVersion configuration = @@ -97,7 +98,7 @@ let generateOverrides = // optimize = true or false // configuration = "Release" or "Debug" // -let generateProjectArtifacts (pc:ProjectConfiguration) outputType (targetFramework:string) configuration = +let generateProjectArtifacts (pc:ProjectConfiguration) outputType (targetFramework:string) configuration languageVersion= let fsharpCoreLocation = let compiler = if outputType = OutputType.Script then @@ -111,7 +112,6 @@ let generateProjectArtifacts (pc:ProjectConfiguration) outputType (targetFramewo "net45" (Path.GetFullPath(__SOURCE_DIRECTORY__) + "/../../artifacts/bin/" + compiler + "/" + configuration + "/" + targetCore + "/FSharp.Core.dll") - let computeSourceItems addDirectory addCondition (compileItem:CompileItem) sources = let computeInclude src = let fileName = if addDirectory then Path.Combine(pc.SourceDirectory, src) else src @@ -148,6 +148,7 @@ let generateProjectArtifacts (pc:ProjectConfiguration) outputType (targetFramewo false $(DEBUG) portable + $(LANGUAGEVERSION) $(OPTIMIZE) false NETCOREAPP @@ -201,12 +202,12 @@ let generateProjectArtifacts (pc:ProjectConfiguration) outputType (targetFramewo |> replaceTokens "$(OPTIMIZE)" optimize |> replaceTokens "$(DEBUG)" debug |> replaceTokens "$(TARGETFRAMEWORK)" targetFramework + |> replaceTokens "$(LANGUAGEVERSION)" languageVersion |> replaceTokens "$(RestoreFromArtifactsPath)" (Path.GetFullPath(__SOURCE_DIRECTORY__) + "/../../artifacts/packages/" + configuration) - generateProjBody let lockObj = obj() -let singleTestBuildAndRunCore cfg copyFiles p = +let singleTestBuildAndRunCore cfg copyFiles p languageVersion = let sources = [] let loadSources = [] let useSources = [] @@ -220,13 +221,13 @@ let singleTestBuildAndRunCore cfg copyFiles p = // compilerType = "coreclr" or "net40" // targetFramework optimize = "net472" OR NETCOREAPP2.1 etc ... // optimize = true or false - let executeSingleTestBuildAndRun outputType compilerType targetFramework optimize = + let executeSingleTestBuildAndRun outputType compilerType targetFramework optimize buildOnly = let mutable result = false let directory = let mutable result = "" lock lockObj <| (fun () -> let rec loop () = - let dir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()) + let dir = Path.Combine(Path.GetTempPath(), "FSharp.Cambridge", Path.GetRandomFileName()) if Directory.Exists(dir) then loop () else @@ -248,6 +249,13 @@ let singleTestBuildAndRunCore cfg copyFiles p = Optimize = optimize } + let findFirstSourceFile (pc:ProjectConfiguration) = + let sources = List.append pc.SourceItems pc.ExtraSourceItems + let found = sources |> List.tryFind(fun source -> File.Exists(Path.Combine(directory, source))) + match found with + | Some p -> Path.Combine(directory, p) + | None -> failwith "Missing SourceFile in test case" + let targetsBody = generateTargets let overridesBody = generateOverrides let targetsFileName = Path.Combine(directory, "Directory.Build.targets") @@ -261,27 +269,33 @@ let singleTestBuildAndRunCore cfg copyFiles p = try File.Delete(Path.Combine(directory, "FSharp.Core.dll")) with _ -> () emitFile targetsFileName targetsBody emitFile overridesFileName overridesBody + let buildOutputFile = Path.Combine(directory, "buildoutput.txt") if outputType = OutputType.Exe then let executeFsc testCompilerVersion targetFramework = let propsBody = generateProps testCompilerVersion cfg.BUILD_CONFIG emitFile propsFileName propsBody - let projectBody = generateProjectArtifacts pc outputType targetFramework cfg.BUILD_CONFIG + let projectBody = generateProjectArtifacts pc outputType targetFramework cfg.BUILD_CONFIG languageVersion emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe (sprintf "run -f %s" targetFramework) - testOkFile.CheckExists() + let cfg = { cfg with Directory = directory } + let result = execBothToOutNoCheck cfg directory buildOutputFile cfg.DotNetExe (sprintf "run -f %s" targetFramework) + if not (buildOnly) then + result |> checkResult + testOkFile.CheckExists() executeFsc compilerType targetFramework + if buildOnly then verifyResults (findFirstSourceFile pc) buildOutputFile else let executeFsi testCompilerVersion targetFramework = let propsBody = generateProps testCompilerVersion cfg.BUILD_CONFIG emitFile propsFileName propsBody - let projectBody = generateProjectArtifacts pc outputType targetFramework cfg.BUILD_CONFIG + let projectBody = generateProjectArtifacts pc outputType targetFramework cfg.BUILD_CONFIG languageVersion emitFile projectFileName projectBody use testOkFile = new FileGuard(Path.Combine(directory, "test.ok")) - exec { cfg with Directory = directory } cfg.DotNetExe "build /t:RunFSharpScript" + let cfg = { cfg with Directory = directory } + execBothToOut cfg directory buildOutputFile cfg.DotNetExe "build /t:RunFSharpScript" testOkFile.CheckExists() executeFsi compilerType targetFramework - result <- true + result <- true finally if result <> false then Directory.Delete(directory, true) @@ -291,13 +305,15 @@ let singleTestBuildAndRunCore cfg copyFiles p = printfn "Filename: %s" projectFileName match p with - | FSC_CORECLR -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" "netcoreapp2.0" true - | FSI_CORECLR -> executeSingleTestBuildAndRun OutputType.Script "coreclr" "netcoreapp2.0" true + | FSC_CORECLR -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" "netcoreapp2.0" true false + | FSC_CORECLR_BUILDONLY -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" "netcoreapp2.0" true true + | FSI_CORECLR -> executeSingleTestBuildAndRun OutputType.Script "coreclr" "netcoreapp2.0" true false #if !FSHARP_SUITE_DRIVES_CORECLR_TESTS - | FSC_OPT_PLUS_DEBUG -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" true - | FSC_OPT_MINUS_DEBUG -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" false - | FSI_FILE -> executeSingleTestBuildAndRun OutputType.Script "net40" "net472" true + | FSC_BUILDONLY -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" false true + | FSC_OPT_PLUS_DEBUG -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" true false + | FSC_OPT_MINUS_DEBUG -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" false false + | FSI_FILE -> executeSingleTestBuildAndRun OutputType.Script "net40" "net472" true false | FSI_STDIN -> use cleanup = (cleanUpFSharpCore cfg) @@ -338,8 +354,8 @@ let singleTestBuildAndRunCore cfg copyFiles p = let sources = extraSources |> List.filter (fileExists cfg) - fsc cfg "%s --optimize -a -o:test--optimize-lib.dll -g" cfg.fsc_flags sources - fsc cfg "%s --optimize -r:test--optimize-lib.dll -o:test--optimize-client-of-lib.exe -g" cfg.fsc_flags sources + fsc cfg "%s --optimize -a -o:test--optimize-lib.dll -g --langversion:preview " cfg.fsc_flags sources + fsc cfg "%s --optimize -r:test--optimize-lib.dll -o:test--optimize-client-of-lib.exe -g --langversion:preview " cfg.fsc_flags sources peverify cfg "test--optimize-lib.dll" peverify cfg "test--optimize-client-of-lib.exe" @@ -348,17 +364,20 @@ let singleTestBuildAndRunCore cfg copyFiles p = testOkFile.CheckExists() #endif - + let singleTestBuildAndRunAux cfg p = - singleTestBuildAndRunCore cfg "" p + singleTestBuildAndRunCore cfg "" p "latest" let singleTestBuildAndRunWithCopyDlls cfg copyFiles p = - singleTestBuildAndRunCore cfg copyFiles p + singleTestBuildAndRunCore cfg copyFiles p "latest" let singleTestBuildAndRun dir p = let cfg = testConfig dir singleTestBuildAndRunAux cfg p +let singleTestBuildAndRunVersion dir p version = + let cfg = testConfig dir + singleTestBuildAndRunCore cfg "" p version let singleNegTest (cfg: TestConfig) testname = @@ -376,7 +395,7 @@ let singleNegTest (cfg: TestConfig) testname = testname + "b.mli"; testname + "b.fsi"; testname + "b.ml"; testname + "b.fs"; ] yield! src |> List.filter (fileExists cfg) - + if fileExists cfg "helloWorldProvider.dll" then yield "-r:helloWorldProvider.dll" diff --git a/tests/fsharp/test-framework.fs b/tests/fsharp/test-framework.fs index 1e3aa9b37a0..cace5cf935c 100644 --- a/tests/fsharp/test-framework.fs +++ b/tests/fsharp/test-framework.fs @@ -435,7 +435,8 @@ let execAppendIgnoreExitCode cfg stdoutPath stderrPath p = Command.exec cfg.Dire let exec cfg p = Command.exec cfg.Directory cfg.EnvironmentVariables execArgs p >> checkResult let execExpectFail cfg p = Command.exec cfg.Directory cfg.EnvironmentVariables execArgs p >> checkErrorLevel1 let execIn cfg workDir p = Command.exec workDir cfg.EnvironmentVariables execArgs p >> checkResult -let execBothToOut cfg workDir outFile p = Command.exec workDir cfg.EnvironmentVariables { execArgs with Output = OutputAndErrorToSameFile(Overwrite(outFile)) } p >> checkResult +let execBothToOutNoCheck cfg workDir outFile p = Command.exec workDir cfg.EnvironmentVariables { execArgs with Output = OutputAndErrorToSameFile(Overwrite(outFile)) } p +let execBothToOut cfg workDir outFile p = execBothToOutNoCheck cfg workDir outFile p >> checkResult let execAppendOutIgnoreExitCode cfg workDir outFile p = Command.exec workDir cfg.EnvironmentVariables { execArgs with Output = Output(Append(outFile)) } p >> alwaysSuccess let execAppendErrExpectFail cfg errPath p = Command.exec cfg.Directory cfg.EnvironmentVariables { execArgs with Output = Error(Overwrite(errPath)) } p >> checkErrorLevel1 let execStdin cfg l p = Command.exec cfg.Directory cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index e302a743771..01bc3f954ea 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -16,10 +16,12 @@ open NUnit.Framework open TestFramework open Scripting open SingleTest +open HandleExpects #if FSHARP_SUITE_DRIVES_CORECLR_TESTS // Use these lines if you want to test CoreCLR let FSC_BASIC = FSC_CORECLR +let FSC_BUILDONLY = FSC_CORECLR_BUILDONLY let FSI_BASIC = FSI_CORECLR #else let FSC_BASIC = FSC_OPT_PLUS_DEBUG @@ -1699,7 +1701,7 @@ module CoreTests = csc cfg """/nologo /r:"%s" /r:lib--optimize.dll /out:test--optimize.exe""" cfg.FSCOREDLLPATH ["test.cs"] - let dicases = ["flag_deterministic_init1.fs"; "lib_deterministic_init1.fs"; "flag_deterministic_init2.fs"; "lib_deterministic_init2.fs"; "flag_deterministic_init3.fs"; "lib_deterministic_init3.fs"; "flag_deterministic_init4.fs"; "lib_deterministic_init4.fs"; "flag_deterministic_init5.fs"; "lib_deterministic_init5.fs"; "flag_deterministic_init6.fs"; "lib_deterministic_init6.fs"; "flag_deterministic_init7.fs"; "lib_deterministic_init7.fs"; "flag_deterministic_init8.fs"; "lib_deterministic_init8.fs"; "flag_deterministic_init9.fs"; "lib_deterministic_init9.fs"; "flag_deterministic_init10.fs"; "lib_deterministic_init10.fs"; "flag_deterministic_init11.fs"; "lib_deterministic_init11.fs"; "flag_deterministic_init12.fs"; "lib_deterministic_init12.fs"; "flag_deterministic_init13.fs"; "lib_deterministic_init13.fs"; "flag_deterministic_init14.fs"; "lib_deterministic_init14.fs"; "flag_deterministic_init15.fs"; "lib_deterministic_init15.fs"; "flag_deterministic_init16.fs"; "lib_deterministic_init16.fs"; "flag_deterministic_init17.fs"; "lib_deterministic_init17.fs"; "flag_deterministic_init18.fs"; "lib_deterministic_init18.fs"; "flag_deterministic_init19.fs"; "lib_deterministic_init19.fs"; "flag_deterministic_init20.fs"; "lib_deterministic_init20.fs"; "flag_deterministic_init21.fs"; "lib_deterministic_init21.fs"; "flag_deterministic_init22.fs"; "lib_deterministic_init22.fs"; "flag_deterministic_init23.fs"; "lib_deterministic_init23.fs"; "flag_deterministic_init24.fs"; "lib_deterministic_init24.fs"; "flag_deterministic_init25.fs"; "lib_deterministic_init25.fs"; "flag_deterministic_init26.fs"; "lib_deterministic_init26.fs"; "flag_deterministic_init27.fs"; "lib_deterministic_init27.fs"; "flag_deterministic_init28.fs"; "lib_deterministic_init28.fs"; "flag_deterministic_init29.fs"; "lib_deterministic_init29.fs"; "flag_deterministic_init30.fs"; "lib_deterministic_init30.fs"; "flag_deterministic_init31.fs"; "lib_deterministic_init31.fs"; "flag_deterministic_init32.fs"; "lib_deterministic_init32.fs"; "flag_deterministic_init33.fs"; "lib_deterministic_init33.fs"; "flag_deterministic_init34.fs"; "lib_deterministic_init34.fs"; "flag_deterministic_init35.fs"; "lib_deterministic_init35.fs"; "flag_deterministic_init36.fs"; "lib_deterministic_init36.fs"; "flag_deterministic_init37.fs"; "lib_deterministic_init37.fs"; "flag_deterministic_init38.fs"; "lib_deterministic_init38.fs"; "flag_deterministic_init39.fs"; "lib_deterministic_init39.fs"; "flag_deterministic_init40.fs"; "lib_deterministic_init40.fs"; "flag_deterministic_init41.fs"; "lib_deterministic_init41.fs"; "flag_deterministic_init42.fs"; "lib_deterministic_init42.fs"; "flag_deterministic_init43.fs"; "lib_deterministic_init43.fs"; "flag_deterministic_init44.fs"; "lib_deterministic_init44.fs"; "flag_deterministic_init45.fs"; "lib_deterministic_init45.fs"; "flag_deterministic_init46.fs"; "lib_deterministic_init46.fs"; "flag_deterministic_init47.fs"; "lib_deterministic_init47.fs"; "flag_deterministic_init48.fs"; "lib_deterministic_init48.fs"; "flag_deterministic_init49.fs"; "lib_deterministic_init49.fs"; "flag_deterministic_init50.fs"; "lib_deterministic_init50.fs"; "flag_deterministic_init51.fs"; "lib_deterministic_init51.fs"; "flag_deterministic_init52.fs"; "lib_deterministic_init52.fs"; "flag_deterministic_init53.fs"; "lib_deterministic_init53.fs"; "flag_deterministic_init54.fs"; "lib_deterministic_init54.fs"; "flag_deterministic_init55.fs"; "lib_deterministic_init55.fs"; "flag_deterministic_init56.fs"; "lib_deterministic_init56.fs"; "flag_deterministic_init57.fs"; "lib_deterministic_init57.fs"; "flag_deterministic_init58.fs"; "lib_deterministic_init58.fs"; "flag_deterministic_init59.fs"; "lib_deterministic_init59.fs"; "flag_deterministic_init60.fs"; "lib_deterministic_init60.fs"; "flag_deterministic_init61.fs"; "lib_deterministic_init61.fs"; "flag_deterministic_init62.fs"; "lib_deterministic_init62.fs"; "flag_deterministic_init63.fs"; "lib_deterministic_init63.fs"; "flag_deterministic_init64.fs"; "lib_deterministic_init64.fs"; "flag_deterministic_init65.fs"; "lib_deterministic_init65.fs"; "flag_deterministic_init66.fs"; "lib_deterministic_init66.fs"; "flag_deterministic_init67.fs"; "lib_deterministic_init67.fs"; "flag_deterministic_init68.fs"; "lib_deterministic_init68.fs"; "flag_deterministic_init69.fs"; "lib_deterministic_init69.fs"; "flag_deterministic_init70.fs"; "lib_deterministic_init70.fs"; "flag_deterministic_init71.fs"; "lib_deterministic_init71.fs"; "flag_deterministic_init72.fs"; "lib_deterministic_init72.fs"; "flag_deterministic_init73.fs"; "lib_deterministic_init73.fs"; "flag_deterministic_init74.fs"; "lib_deterministic_init74.fs"; "flag_deterministic_init75.fs"; "lib_deterministic_init75.fs"; "flag_deterministic_init76.fs"; "lib_deterministic_init76.fs"; "flag_deterministic_init77.fs"; "lib_deterministic_init77.fs"; "flag_deterministic_init78.fs"; "lib_deterministic_init78.fs"; "flag_deterministic_init79.fs"; "lib_deterministic_init79.fs"; "flag_deterministic_init80.fs"; "lib_deterministic_init80.fs"; "flag_deterministic_init81.fs"; "lib_deterministic_init81.fs"; "flag_deterministic_init82.fs"; "lib_deterministic_init82.fs"; "flag_deterministic_init83.fs"; "lib_deterministic_init83.fs"; "flag_deterministic_init84.fs"; "lib_deterministic_init84.fs"; "flag_deterministic_init85.fs"; "lib_deterministic_init85.fs"] + let dicases = ["flag_deterministic_init1.fs"; "lib_deterministic_init1.fs"; "flag_deterministic_init2.fs"; "lib_deterministic_init2.fs"; "flag_deterministic_init3.fs"; "lib_deterministic_init3.fs"; "flag_deterministic_init4.fs"; "lib_deterministic_init4.fs"; "flag_deterministic_init5.fs"; "lib_deterministic_init5.fs"; "flag_deterministic_init6.fs"; "lib_deterministic_init6.fs"; "flag_deterministic_init7.fs"; "lib_deterministic_init7.fs"; "flag_deterministic_init8.fs"; "lib_deterministic_init8.fs"; "flag_deterministic_init9.fs"; "lib_deterministic_init9.fs"; "flag_deterministic_init10.fs"; "lib_deterministic_init10.fs"; "flag_deterministic_init11.fs"; "lib_deterministic_init11.fs"; "flag_deterministic_init12.fs"; "lib_deterministic_init12.fs"; "flag_deterministic_init13.fs"; "lib_deterministic_init13.fs"; "flag_deterministic_init14.fs"; "lib_deterministic_init14.fs"; "flag_deterministic_init15.fs"; "lib_deterministic_init15.fs"; "flag_deterministic_init16.fs"; "lib_deterministic_init16.fs"; "flag_deterministic_init17.fs"; "lib_deterministic_init17.fs"; "flag_deterministic_init18.fs"; "lib_deterministic_init18.fs"; "flag_deterministic_init19.fs"; "lib_deterministic_init19.fs"; "flag_deterministic_init20.fs"; "lib_deterministic_init20.fs"; "flag_deterministic_init21.fs"; "lib_deterministic_init21.fs"; "flag_deterministic_init22.fs"; "lib_deterministic_init22.fs"; "flag_deterministic_init23.fs"; "lib_deterministic_init23.fs"; "flag_deterministic_init24.fs"; "lib_deterministic_init24.fs"; "flag_deterministic_init25.fs"; "lib_deterministic_init25.fs"; "flag_deterministic_init26.fs"; "lib_deterministic_init26.fs"; "flag_deterministic_init27.fs"; "lib_deterministic_init27.fs"; "flag_deterministic_init28.fs"; "lib_deterministic_init28.fs"; "flag_deterministic_init29.fs"; "lib_deterministic_init29.fs"; "flag_deterministic_init30.fs"; "lib_deterministic_init30.fs"; "flag_deterministic_init31.fs"; "lib_deterministic_init31.fs"; "flag_deterministic_init32.fs"; "lib_deterministic_init32.fs"; "flag_deterministic_init33.fs"; "lib_deterministic_init33.fs"; "flag_deterministic_init34.fs"; "lib_deterministic_init34.fs"; "flag_deterministic_init35.fs"; "lib_deterministic_init35.fs"; "flag_deterministic_init36.fs"; "lib_deterministic_init36.fs"; "flag_deterministic_init37.fs"; "lib_deterministic_init37.fs"; "flag_deterministic_init38.fs"; "lib_deterministic_init38.fs"; "flag_deterministic_init39.fs"; "lib_deterministic_init39.fs"; "flag_deterministic_init40.fs"; "lib_deterministic_init40.fs"; "flag_deterministic_init41.fs"; "lib_deterministic_init41.fs"; "flag_deterministic_init42.fs"; "lib_deterministic_init42.fs"; "flag_deterministic_init43.fs"; "lib_deterministic_init43.fs"; "flag_deterministic_init44.fs"; "lib_deterministic_init44.fs"; "flag_deterministic_init45.fs"; "lib_deterministic_init45.fs"; "flag_deterministic_init46.fs"; "lib_deterministic_init46.fs"; "flag_deterministic_init47.fs"; "lib_deterministic_init47.fs"; "flag_deterministic_init48.fs"; "lib_deterministic_init48.fs"; "flag_deterministic_init49.fs"; "lib_deterministic_init49.fs"; "flag_deterministic_init50.fs"; "lib_deterministic_init50.fs"; "flag_deterministic_init51.fs"; "lib_deterministic_init51.fs"; "flag_deterministic_init52.fs"; "lib_deterministic_init52.fs"; "flag_deterministic_init53.fs"; "lib_deterministic_init53.fs"; "flag_deterministic_init54.fs"; "lib_deterministic_init54.fs"; "flag_deterministic_init55.fs"; "lib_deterministic_init55.fs"; "flag_deterministic_init56.fs"; "lib_deterministic_init56.fs"; "flag_deterministic_init57.fs"; "lib_deterministic_init57.fs"; "flag_deterministic_init58.fs"; "lib_deterministic_init58.fs"; "flag_deterministic_init59.fs"; "lib_deterministic_init59.fs"; "flag_deterministic_init60.fs"; "lib_deterministic_init60.fs"; "flag_deterministic_init61.fs"; "lib_deterministic_init61.fs"; "flag_deterministic_init62.fs"; "lib_deterministic_init62.fs"; "flag_deterministic_init63.fs"; "lib_deterministic_init63.fs"; "flag_deterministic_init64.fs"; "lib_deterministic_init64.fs"; "flag_deterministic_init65.fs"; "lib_deterministic_init65.fs"; "flag_deterministic_init66.fs"; "lib_deterministic_init66.fs"; "flag_deterministic_init67.fs"; "lib_deterministic_init67.fs"; "flag_deterministic_init68.fs"; "lib_deterministic_init68.fs"; "flag_deterministic_init69.fs"; "lib_deterministic_init69.fs"; "flag_deterministic_init70.fs"; "lib_deterministic_init70.fs"; "flag_deterministic_init71.fs"; "lib_deterministic_init71.fs"; "flag_deterministic_init72.fs"; "lib_deterministic_init72.fs"; "flag_deterministic_init73.fs"; "lib_deterministic_init73.fs"; "flag_deterministic_init74.fs"; "lib_deterministic_init74.fs"; "flag_deterministic_init75.fs"; "lib_deterministic_init75.fs"; "flag_deterministic_init76.fs"; "lib_deterministic_init76.fs"; "flag_deterministic_init77.fs"; "lib_deterministic_init77.fs"; "flag_deterministic_init78.fs"; "lib_deterministic_init78.fs"; "flag_deterministic_init79.fs"; "lib_deterministic_init79.fs"; "flag_deterministic_init80.fs"; "lib_deterministic_init80.fs"; "flag_deterministic_init81.fs"; "lib_deterministic_init81.fs"; "flag_deterministic_init82.fs"; "lib_deterministic_init82.fs"; "flag_deterministic_init83.fs"; "lib_deterministic_init83.fs"; "flag_deterministic_init84.fs"; "lib_deterministic_init84.fs"; "flag_deterministic_init85.fs"; "lib_deterministic_init85.fs"] fsc cfg "%s --optimize- -o test_deterministic_init.exe" cfg.fsc_flags (dicases @ ["test_deterministic_init.fs"]) @@ -1784,7 +1786,7 @@ module CoreTests = exec cfg ("." ++ "test.exe") "" testOkFile.CheckExists() - + [] let verify () = let cfg = testConfig "core/verify" @@ -1802,6 +1804,13 @@ module CoreTests = peverifyWithArgs cfg "/nologo" "xmlverify.exe" #endif +module VersionTests = + [] + let ``member-selfidentifier-version4.6``() = singleTestBuildAndRunVersion "core/members/self-identifier/version46" FSC_BUILDONLY "4.6" + + [] + let ``member-selfidentifier-version4.7``() = singleTestBuildAndRunVersion "core/members/self-identifier/version47" FSC_BUILDONLY "preview" + #if !FSHARP_SUITE_DRIVES_CORECLR_TESTS module ToolsTests =