diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 5585ae6a6f9..63dba3fed83 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -404,6 +404,7 @@ let warningOn err level specificWarnOn = | 1182 -> false // chkUnusedValue - off by default | 3218 -> false // ArgumentsInSigAndImplMismatch - off by default | 3180 -> false // abImplicitHeapAllocation - off by default + | 3390 -> false // xmlDocBadlyFormed - off by default | _ -> level >= GetWarningLevel err let SplitRelatedDiagnostics(err: PhasedDiagnostic) : PhasedDiagnostic * PhasedDiagnostic list = diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index b5d1d9806ec..2ad9d2c35ba 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1540,3 +1540,6 @@ forFormatInvalidForInterpolated4,"Interpolated strings used as type IFormattable 3382,parsEmptyFillInInterpolatedString,"Invalid interpolated string. This interpolated string expression fill is empty, an expression was expected." 3383,lexRBraceInInterpolatedString,"A '}}' character must be escaped (by doubling) in an interpolated string." #3501 "This construct is not supported by your version of the F# compiler" CompilerMessage(ExperimentalAttributeMessages.NotSupportedYet, 3501, IsError=true) +3390,xmlDocBadlyFormed,"This XML comment is invalid: '%s'" +3390,xmlDocMissingParameterName,"This XML comment is invalid: missing parameter name" +3390,xmlDocInvalidParameterName,"This XML comment is invalid: invalid parameter reference '%s'" diff --git a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index c83d93afc3f..b00fd69c9ce 100644 --- a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -21,7 +21,7 @@ FSharp.Compiler.Service.nuspec true The F# Compiler Services package For F# $(FSLanguageVersion) exposes additional functionality for implementing F# language bindings, additional tools based on the compiler or refactoring tools. The package also includes F# interactive service that can be used for embedding F# scripting into your applications. Contains code from the F# Software Foundation. - /blob/main/release-notes.md#FSharp-Compilere-Service-$(FSharpCompilerServiceReleaseNotesVersion) + /blob/main/release-notes.md#FSharp-Compiler-Service-$(FSharpCompilerServiceReleaseNotesVersion) F#, fsharp, interactive, compiler, editor diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 8eb2bb01a74..28f398848e0 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -9,7 +9,7 @@ true $(DefineConstants);FSHARP_CORE BUILDING_WITH_LKG;$(DefineConstants) - $(OtherFlags) --warnon:1182 --compiling-fslib --compiling-fslib-40 --maxerrors:20 --extraoptimizationloops:1 --nowarn:57 + $(OtherFlags) --warnon:1182 --warnon:3390 --compiling-fslib --compiling-fslib-40 --maxerrors:20 --extraoptimizationloops:1 --nowarn:57 true true diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 29750a8cc50..307fd22c20a 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -370,7 +370,7 @@ namespace Microsoft.FSharp.Core [] type int16<[] 'Measure> = int16 [] type int64<[] 'Measure> = int64 - /// Represents a managed pointer in F# code. + /// Represents a managed pointer in F# code. type byref<'T> = (# "!0&" #) /// Represents a managed pointer in F# code. diff --git a/src/fsharp/ParseHelpers.fs b/src/fsharp/ParseHelpers.fs index 33e7872b186..6a94962108a 100644 --- a/src/fsharp/ParseHelpers.fs +++ b/src/fsharp/ParseHelpers.fs @@ -85,7 +85,7 @@ module LexbufLocalXmlDocStore = lexbuf.BufferLocalStore.[xmlDocKey] <- box (XmlDocCollector()) /// Called from the lexer to save a single line of XML doc comment. - let internal SaveXmlDocLine (lexbuf: Lexbuf, lineText, pos) = + let internal SaveXmlDocLine (lexbuf: Lexbuf, lineText, range: range) = let collector = match lexbuf.BufferLocalStore.TryGetValue xmlDocKey with | true, collector -> collector @@ -94,7 +94,7 @@ module LexbufLocalXmlDocStore = lexbuf.BufferLocalStore.[xmlDocKey] <- collector collector let collector = unbox(collector) - collector.AddXmlDocLine(lineText, pos) + collector.AddXmlDocLine(lineText, range) /// Called from the parser each time we parse a construct that marks the end of an XML doc comment range, /// e.g. a 'type' declaration. The markerRange is the range of the keyword that delimits the construct. diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index 46019fae45b..c0c82ded20e 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -745,7 +745,9 @@ type Entity = member x.XmlDoc = #if !NO_EXTENSIONTYPING match x.TypeReprInfo with - | TProvidedTypeExtensionPoint info -> XmlDoc (info.ProvidedType.PUntaintNoFailure(fun st -> (st :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(info.ProvidedType.TypeProvider.PUntaintNoFailure id))) + | TProvidedTypeExtensionPoint info -> + let lines = info.ProvidedType.PUntaintNoFailure(fun st -> (st :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(info.ProvidedType.TypeProvider.PUntaintNoFailure id)) + XmlDoc (lines |> Array.map (fun line -> line, x.DefinitionRange)) | _ -> #endif match x.entity_opt_data with diff --git a/src/fsharp/TypedTreePickle.fs b/src/fsharp/TypedTreePickle.fs index 837021b92e2..6a0deb51f4a 100644 --- a/src/fsharp/TypedTreePickle.fs +++ b/src/fsharp/TypedTreePickle.fs @@ -1345,7 +1345,7 @@ let p_range (x: range) st = let p_dummy_range : range pickler = fun _x _st -> () let p_ident (x: Ident) st = p_tup2 p_string p_range (x.idText, x.idRange) st -let p_xmldoc (XmlDoc x) st = p_array p_string x st +let p_xmldoc (XmlDoc lines) st = p_array p_string (Array.map fst lines) st let u_pos st = let a = u_int st in let b = u_int st in mkPos a b let u_range st = let a = u_string st in let b = u_pos st in let c = u_pos st in mkRange a b c @@ -1353,7 +1353,7 @@ let u_range st = let a = u_string st in let b = u_pos st in let c = u_pos st in // Most ranges (e.g. on optimization expressions) can be elided from stored data let u_dummy_range : range unpickler = fun _st -> range0 let u_ident st = let a = u_string st in let b = u_range st in ident(a, b) -let u_xmldoc st = XmlDoc (u_array u_string st) +let u_xmldoc st = XmlDoc (u_array u_string st |> Array.map (fun line -> line, range0)) let p_local_item_ref ctxt tab st = p_osgn_ref ctxt tab st diff --git a/src/fsharp/XmlDoc.fs b/src/fsharp/XmlDoc.fs index dc183affeb6..7560ac1804e 100644 --- a/src/fsharp/XmlDoc.fs +++ b/src/fsharp/XmlDoc.fs @@ -2,37 +2,61 @@ module public FSharp.Compiler.XmlDoc +open System +open System.Xml.Linq +open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Lib open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.Range -/// Represents the final form of collected XmlDoc lines +/// Represents collected XmlDoc lines type XmlDoc = - | XmlDoc of string[] + | XmlDoc of (string * range)[] static member Empty = XmlDocStatics.Empty - member x.NonEmpty = (let (XmlDoc lines) = x in lines.Length <> 0) + member x.IsEmpty = + let (XmlDoc lines) = x + lines |> Array.forall (fst >> String.IsNullOrWhiteSpace) + + member x.NonEmpty = not x.IsEmpty - static member Merge (XmlDoc lines) (XmlDoc lines') = XmlDoc (Array.append lines lines') + static member Merge (XmlDoc lines) (XmlDoc lines') = + XmlDoc (Array.append lines lines') + member x.Range = + let (XmlDoc lines) = x + match lines with + | [| |] -> Range.range0 + | _ -> Array.reduce Range.unionRanges (Array.map snd lines) + /// This code runs for .XML generation and thus influences cross-project xmldoc tooltips; for within-project tooltips, /// see XmlDocumentation.fs in the language service static member Process (XmlDoc lines) = - let rec processLines (lines: string list) = + let rec processLines (lines: (string * range) list) = match lines with | [] -> [] - | (lineA :: rest) as lines -> + | ((lineA, m) :: rest) as lines -> let lineAT = lineA.TrimStart([|' '|]) if lineAT = "" then processLines rest else if lineAT.StartsWithOrdinal("<") then lines - else [""] @ - (lines |> List.map (fun line -> Microsoft.FSharp.Core.XmlAdapters.escape line)) @ - [""] + else [("", m)] @ + (lines |> List.map (map1Of2 Microsoft.FSharp.Core.XmlAdapters.escape)) @ + [("", m)] let lines = processLines (Array.toList lines) if isNil lines then XmlDoc.Empty else XmlDoc (Array.ofList lines) + member x.GetXmlText() = + match XmlDoc.Process x with + | XmlDoc [| |] -> "" + | XmlDoc strs -> + strs + |> Array.toList + |> List.map fst + |> String.concat Environment.NewLine + // Discriminated unions can't contain statics, so we use a separate type and XmlDocStatics() = @@ -42,14 +66,14 @@ and XmlDocStatics() = /// Used to collect XML documentation during lexing and parsing. type XmlDocCollector() = - let mutable savedLines = new ResizeArray<(string * pos)>() + let mutable savedLines = new ResizeArray<(string * range)>() let mutable savedGrabPoints = new ResizeArray() let posCompare p1 p2 = if posGeq p1 p2 then 1 else if posEq p1 p2 then 0 else -1 let savedGrabPointsAsArray = lazy (savedGrabPoints.ToArray() |> Array.sortWith posCompare) let savedLinesAsArray = - lazy (savedLines.ToArray() |> Array.sortWith (fun (_, p1) (_, p2) -> posCompare p1 p2)) + lazy (savedLines.ToArray() |> Array.sortWith (fun (_, p1) (_, p2) -> posCompare p1.End p2.End)) let check() = // can't add more XmlDoc elements to XmlDocCollector after extracting first XmlDoc from the overall results @@ -59,15 +83,15 @@ type XmlDocCollector() = check() savedGrabPoints.Add pos - member x.AddXmlDocLine(line, pos) = + member x.AddXmlDocLine(line, range) = check() - savedLines.Add(line, pos) + savedLines.Add(line, range) member x.LinesBefore grabPointPos = try let lines = savedLinesAsArray.Force() let grabPoints = savedGrabPointsAsArray.Force() - let firstLineIndexAfterGrabPoint = Array.findFirstIndexWhereTrue lines (fun (_, pos) -> posGeq pos grabPointPos) + let firstLineIndexAfterGrabPoint = Array.findFirstIndexWhereTrue lines (fun (_, m) -> posGeq m.End grabPointPos) let grabPointIndex = Array.findFirstIndexWhereTrue grabPoints (fun pos -> posGeq pos grabPointPos) assert (posEq grabPoints.[grabPointIndex] grabPointPos) let firstLineIndexAfterPrevGrabPoint = @@ -75,10 +99,10 @@ type XmlDocCollector() = 0 else let prevGrabPointPos = grabPoints.[grabPointIndex-1] - Array.findFirstIndexWhereTrue lines (fun (_, pos) -> posGeq pos prevGrabPointPos) + Array.findFirstIndexWhereTrue lines (fun (_, m) -> posGeq m.End prevGrabPointPos) let lines = lines.[firstLineIndexAfterPrevGrabPoint..firstLineIndexAfterGrabPoint-1] - lines |> Array.map fst + lines with e -> [| |] @@ -89,13 +113,42 @@ type PreXmlDoc = | PreXmlDocEmpty member x.ToXmlDoc() = - match x with - | PreXmlMerge(a, b) -> XmlDoc.Merge (a.ToXmlDoc()) (b.ToXmlDoc()) - | PreXmlDocEmpty -> XmlDoc.Empty - | PreXmlDoc (pos, collector) -> - let lines = collector.LinesBefore pos - if lines.Length = 0 then XmlDoc.Empty - else XmlDoc lines + let doc = + match x with + | PreXmlMerge(a, b) -> XmlDoc.Merge (a.ToXmlDoc()) (b.ToXmlDoc()) + | PreXmlDocEmpty -> XmlDoc.Empty + | PreXmlDoc (pos, collector) -> + let lines = collector.LinesBefore pos + if lines.Length = 0 then XmlDoc.Empty + else XmlDoc lines + if doc.NonEmpty then + try + // We must wrap with in order to have only one root element + let xml = XDocument.Parse("\n"+doc.GetXmlText()+"\n", LoadOptions.SetLineInfo) + + // Note, the parameter names are curently only checked for internal + // consistency, so parameter references must match an XML doc parameter name. + let paramNames = + [ for p in xml.Descendants(XName.op_Implicit "param") do + match p.Attribute(XName.op_Implicit "name") with + | null -> + warning (Error (FSComp.SR.xmlDocMissingParameterName(), doc.Range)) + | nm -> + nm.Value ] + + for pref in xml.Descendants(XName.op_Implicit "paramref") do + match pref.Attribute(XName.op_Implicit "name") with + | null -> warning (Error (FSComp.SR.xmlDocMissingParameterName(), doc.Range)) + | attr -> + let nm = attr.Value + if not (paramNames |> List.contains nm) then + warning (Error (FSComp.SR.xmlDocInvalidParameterName(nm), doc.Range)) + xml |> ignore + + with e -> + warning (Error (FSComp.SR.xmlDocBadlyFormed(e.Message), doc.Range)) + doc + static member CreateFromGrabPoint(collector: XmlDocCollector, grabPointPos) = collector.AddGrabPoint grabPointPos diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 68e768acbf6..46f82dbff6d 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -328,11 +328,6 @@ module InterfaceFileWriter = module XmlDocWriter = - let getDoc xmlDoc = - match XmlDoc.Process xmlDoc with - | XmlDoc [| |] -> "" - | XmlDoc strs -> strs |> Array.toList |> String.concat Environment.NewLine - let hasDoc xmlDoc = // No need to process the xml doc - just need to know if there's anything there match xmlDoc with @@ -389,7 +384,7 @@ module XmlDocWriter = let mutable members = [] let addMember id xmlDoc = if hasDoc xmlDoc then - let doc = getDoc xmlDoc + let doc = xmlDoc.GetXmlText() members <- (id, doc) :: members let doVal (v: Val) = addMember v.XmlDocSig v.XmlDoc let doUnionCase (uc: UnionCase) = addMember uc.XmlDocSig uc.XmlDoc diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 8b909c41829..bf70d34431a 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1064,7 +1064,9 @@ type MethInfo = | DefaultStructCtor _ -> XmlDoc.Empty #if !NO_EXTENSIONTYPING | ProvidedMeth(_, mi, _, m)-> - XmlDoc (mi.PUntaint((fun mix -> (mix :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(mi.TypeProvider.PUntaintNoFailure id)), m)) + let lines = mi.PUntaint((fun mix -> (mix :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(mi.TypeProvider.PUntaintNoFailure id)), m) + let lines = lines |> Array.map (fun line -> line, m) + XmlDoc lines #endif /// Try to get an arbitrary F# ValRef associated with the member. This is to determine if the member is virtual, amongst other things. @@ -2162,7 +2164,9 @@ type PropInfo = | FSProp(_, _, None, None) -> failwith "unreachable" #if !NO_EXTENSIONTYPING | ProvidedProp(_, pi, m) -> - XmlDoc (pi.PUntaint((fun pix -> (pix :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(pi.TypeProvider.PUntaintNoFailure id)), m)) + let lines = pi.PUntaint((fun pix -> (pix :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(pi.TypeProvider.PUntaintNoFailure id)), m) + let lines = lines |> Array.map (fun line -> line, m) + XmlDoc lines #endif /// Get the TcGlobals associated with the object @@ -2416,7 +2420,9 @@ type EventInfo = | FSEvent (_, p, _, _) -> p.XmlDoc #if !NO_EXTENSIONTYPING | ProvidedEvent (_, ei, m) -> - XmlDoc (ei.PUntaint((fun eix -> (eix :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(ei.TypeProvider.PUntaintNoFailure id)), m)) + let lines = ei.PUntaint((fun eix -> (eix :> IProvidedCustomAttributeProvider).GetXmlDocAttributes(ei.TypeProvider.PUntaintNoFailure id)), m) + let lines = lines |> Array.map (fun line -> line, m) + XmlDoc lines #endif /// Get the logical name of the event. diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index 5322a3ddf48..e46718a3d1f 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -166,15 +166,17 @@ let startString args (lexbuf: UnicodeLexing.Lexbuf) = // Utility functions for processing XML documentation -let trySaveXmlDoc lexbuf (buff:option) = +let trySaveXmlDoc (lexbuf: LexBuffer) (buff: (range * StringBuilder) option) = match buff with | None -> () - | Some sb -> LexbufLocalXmlDocStore.SaveXmlDocLine (lexbuf, sb.ToString(), posOfLexPosition lexbuf.StartPos) + | Some (start, sb) -> + let xmlCommentLineRange = mkFileIndexRange start.FileIndex start.Start (posOfLexPosition lexbuf.StartPos) + LexbufLocalXmlDocStore.SaveXmlDocLine (lexbuf, sb.ToString(), xmlCommentLineRange) -let tryAppendXmlDoc (buff:option) (s:string) = +let tryAppendXmlDoc (buff: (range * StringBuilder) option) (s:string) = match buff with | None -> () - | Some sb -> ignore(sb.Append s) + | Some (_, sb) -> ignore(sb.Append s) // Utilities for parsing #if/#else/#endif @@ -660,7 +662,7 @@ rule token args skip = parse let doc = lexemeTrimLeft lexbuf 3 let sb = (new StringBuilder(100)).Append(doc) if not skip then LINE_COMMENT (LexCont.SingleLineComment(args.ifdefStack, args.stringNest, 1, m)) - else singleLineComment (Some sb,1,m,args) skip lexbuf } + else singleLineComment (Some (m, sb),1,m,args) skip lexbuf } | "//" op_char* { // Need to read all operator symbols too, otherwise it might be parsed by a rule below diff --git a/src/fsharp/service/ServiceXmlDocParser.fs b/src/fsharp/service/ServiceXmlDocParser.fs index 01073ec599a..a13edf537cf 100644 --- a/src/fsharp/service/ServiceXmlDocParser.fs +++ b/src/fsharp/service/ServiceXmlDocParser.fs @@ -49,12 +49,10 @@ module XmlDocParsing = i let isEmptyXmlDoc (preXmlDoc: PreXmlDoc) = - match preXmlDoc.ToXmlDoc() with - | XmlDoc [||] -> true - | XmlDoc [|x|] when x.Trim() = "" -> true - | _ -> false + preXmlDoc.ToXmlDoc().IsEmpty - let rec getXmlDocablesSynModuleDecl = function + let rec getXmlDocablesSynModuleDecl decl = + match decl with | SynModuleDecl.NestedModule(_, _, synModuleDecls, _, _) -> (synModuleDecls |> List.collect getXmlDocablesSynModuleDecl) | SynModuleDecl.Let(_, synBindingList, range) -> diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index bbe3e5b2de8..a9d147873d1 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -662,13 +662,14 @@ module internal SymbolHelpers = let GetXmlCommentForItemAux (xmlDoc: XmlDoc option) (infoReader: InfoReader) m d = let result = match xmlDoc with - | None | Some (XmlDoc [| |]) -> "" - | Some (XmlDoc l) -> + | None -> "" + | Some xmlDoc when xmlDoc.IsEmpty -> "" + | Some (XmlDoc lines) -> bufs (fun os -> bprintf os "\n" - l |> Array.iter (fun (s: string) -> + lines |> Array.iter (fun (line, _) -> // Note: this code runs for local/within-project xmldoc tooltips, but not for cross-project or .XML - bprintf os "\n%s" s)) + bprintf os "\n%s" line)) if String.IsNullOrEmpty result then GetXmlDocHelpSigOfItemForLookup infoReader m d diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 4fe8986ec97..d0bb6c2aa13 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -78,7 +78,8 @@ module Impl = let makeReadOnlyCollection (arr: seq<'T>) = System.Collections.ObjectModel.ReadOnlyCollection<_>(Seq.toArray arr) :> IList<_> - let makeXmlDoc (XmlDoc x) = makeReadOnlyCollection x + let makeXmlDoc (XmlDoc lines) = + makeReadOnlyCollection (Array.map fst lines) let rescopeEntity optViewedCcu (entity: Entity) = match optViewedCcu with diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index ee4520e2f46..3dc155020cc 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -522,6 +522,21 @@ Pro odkazy na rozhraní .NET používejte referenční sestavení, pokud jsou k dispozici (ve výchozím nastavení povolené). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Zvažte použití parametru yield! namísto yield. diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 084d3c4031e..292f6c66669 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -522,6 +522,21 @@ Verweisassemblys für .NET Framework-Verweise verwenden, wenn verfügbar (standardmäßig aktiviert). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Verwenden Sie ggf. "yield!" anstelle von "yield". diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 83ba01bb5a5..c7e00ed68b6 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -522,6 +522,21 @@ Use ensamblados de referencia para las referencias de .NET Framework cuando estén disponibles (habilitado de forma predeterminada). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Considere la posibilidad de usar "yield!" en lugar de "yield". diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 5e2edeccf43..c64e4e544a8 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -522,6 +522,21 @@ Utilisez des assemblys de référence pour les références .NET Framework quand ils sont disponibles (activé par défaut). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Utilisez 'yield!' à la place de 'yield'. diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index d870e6feaac..dbd6a9eada2 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -522,6 +522,21 @@ Usa gli assembly di riferimento per i riferimenti a .NET Framework quando disponibili (abilitato per impostazione predefinita). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Provare a usare 'yield!' invece di 'yield'. diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 634025e3144..767dd75391e 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -522,6 +522,21 @@ 使用可能な場合は、.NET Framework リファレンスの参照アセンブリを使用します (既定で有効)。 + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. 'yield' の代わりに 'yield!' を使うことを検討してください。 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 9684a8b6077..a7ba88f7d29 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -522,6 +522,21 @@ 기본적으로 활성화되는 참조 어셈블리를 .NET Framework 참조에 사용합니다(사용 가능한 경우). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. 'yield'가 아닌 'yield!'를 사용하세요. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 77b9a86179f..8b1a2b6cd59 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -522,6 +522,21 @@ Użyj zestawów odwołań dla odwołań do programu .NET Framework, gdy są dostępne (domyślnie włączone). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Rozważ użycie polecenia „yield!” zamiast „yield”. diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 2bb3ed9fff6..5648c5a32b7 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -522,6 +522,21 @@ Use assemblies de referência para referências do .NET Framework quando disponível (habilitado por padrão). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Considere usar 'yield!' em vez de 'yield'. diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 80477df0542..13b5b7cee10 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -522,6 +522,21 @@ Использовать базовые сборки для ссылок на платформу .NET, если базовые сборки доступны (включено по умолчанию). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. Рекомендуется использовать "yield!" вместо "yield". diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 86a7308ffbd..370df29dc88 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -522,6 +522,21 @@ Kullanılabilir olduğunda, .NET Framework başvuruları için başvuru bütünleştirilmiş kodlarını kullanın (Varsayılan olarak etkindir). + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. 'yield' yerine 'yield!' kullanmayı deneyin. diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 7b7b5e75ac9..a1a8e6f59f4 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -522,6 +522,21 @@ 如果可用,请对 .NET Framework 引用使用引用程序集(默认启用)。 + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. 考虑使用 "yield!",而非 "yield"。 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 6db7230450c..8fd91081031 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -522,6 +522,21 @@ 請在可行的情況下使用適用於 .NET 架構參考的參考組件 (預設會啟用)。 + + This XML comment is invalid: '{0}' + This XML comment is invalid: '{0}' + + + + This XML comment is invalid: invalid parameter reference '{0}' + This XML comment is invalid: invalid parameter reference '{0}' + + + + This XML comment is invalid: missing parameter name + This XML comment is invalid: missing parameter name + + Consider using 'yield!' instead of 'yield'. 請考慮使用 'yield!' 而不使用 'yield'。 diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index f97a823591c..27f4cb4c6dd 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -40,6 +40,7 @@ + @@ -54,4 +55,8 @@ + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/XmlComments.fs b/tests/FSharp.Compiler.ComponentTests/Language/XmlComments.fs new file mode 100644 index 00000000000..8881d1a4712 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/XmlComments.fs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.ComponentTests.XmlComments + +open Xunit +open FSharp.Test.Utilities.Compiler + +module XmlCommentChecking = + + [] + let ``invalid XML is reported`` () = + Fsx""" +/// +let x = 1 + +/// +/// Yo +/// Yo +module M = + /// < + let y = 1 + + """ + |> withXmlCommentChecking + |> ignoreWarnings // means "don't treat warnings as errors" + |> compile + |> shouldSucceed + |> withDiagnostics + [ (Warning 3390, Line 2, Col 1, Line 2, Col 14, + "This XML comment is invalid: 'The 'summary' start tag on line 2 position 3 does not match the end tag of 'doc'. Line 3, position 3.'"); + (Warning 3390, Line 5, Col 1, Line 7, Col 21, + """This XML comment is invalid: 'The 'remark' start tag on line 3 position 3 does not match the end tag of 'rem'. Line 3, position 14.'"""); + (Warning 3390, Line 9, Col 5, Line 9, Col 20, + "This XML comment is invalid: 'Name cannot begin with the '\n' character, hexadecimal value 0x0A. Line 2, position 13.'") + ] + [] + let ``invalid parameter reference is reported`` () = + Fsx""" + /// Return + /// the parameter + let f a = a + """ + |> withXmlCommentChecking + |> ignoreWarnings // means "don't treat warnings as errors" + |> compile + |> shouldSucceed + |> withDiagnostics + [ (Warning 3390, Line 2, Col 5, Line 3, Col 48, + "This XML comment is invalid: invalid parameter reference 'b'"); + ] diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.net472.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.net472.fs index 0cacf6073ee..55dd7b6127e 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.net472.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.net472.fs @@ -41930,25 +41930,27 @@ FSharp.Compiler.XmlDoc+XmlDoc: Boolean Equals(System.Object, System.Collections. FSharp.Compiler.XmlDoc+XmlDoc: Boolean Equals(XmlDoc) FSharp.Compiler.XmlDoc+XmlDoc: Boolean NonEmpty FSharp.Compiler.XmlDoc+XmlDoc: Boolean get_NonEmpty() -FSharp.Compiler.XmlDoc+XmlDoc: Int32 CompareTo(System.Object) -FSharp.Compiler.XmlDoc+XmlDoc: Int32 CompareTo(System.Object, System.Collections.IComparer) -FSharp.Compiler.XmlDoc+XmlDoc: Int32 CompareTo(XmlDoc) FSharp.Compiler.XmlDoc+XmlDoc: Int32 GetHashCode() FSharp.Compiler.XmlDoc+XmlDoc: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.XmlDoc+XmlDoc: Int32 Tag FSharp.Compiler.XmlDoc+XmlDoc: Int32 get_Tag() FSharp.Compiler.XmlDoc+XmlDoc: System.String ToString() -FSharp.Compiler.XmlDoc+XmlDoc: System.String[] Item -FSharp.Compiler.XmlDoc+XmlDoc: System.String[] get_Item() FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc Empty FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc Merge(XmlDoc, XmlDoc) -FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc NewXmlDoc(System.String[]) FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc Process(XmlDoc) FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc get_Empty() -FSharp.Compiler.XmlDoc+XmlDocCollector: System.String[] LinesBefore(pos) +FSharp.Compiler.XmlDoc+XmlDoc: Boolean IsEmpty +FSharp.Compiler.XmlDoc+XmlDoc: Boolean get_IsEmpty() +FSharp.Compiler.XmlDoc+XmlDoc: System.String GetXmlText() +FSharp.Compiler.XmlDoc+XmlDoc: System.Tuple`2[System.String,FSharp.Compiler.Range+range][] Item +FSharp.Compiler.XmlDoc+XmlDoc: System.Tuple`2[System.String,FSharp.Compiler.Range+range][] get_Item() +FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc NewXmlDoc(System.Tuple`2[System.String,FSharp.Compiler.Range+range][]) +FSharp.Compiler.XmlDoc+XmlDoc: range Range +FSharp.Compiler.XmlDoc+XmlDoc: range get_Range() +FSharp.Compiler.XmlDoc+XmlDocCollector: System.Tuple`2[System.String,FSharp.Compiler.Range+range][] LinesBefore(pos) +FSharp.Compiler.XmlDoc+XmlDocCollector: Void AddXmlDocLine(System.String, range) FSharp.Compiler.XmlDoc+XmlDocCollector: Void .ctor() FSharp.Compiler.XmlDoc+XmlDocCollector: Void AddGrabPoint(pos) -FSharp.Compiler.XmlDoc+XmlDocCollector: Void AddXmlDocLine(System.String, pos) FSharp.Compiler.XmlDoc+XmlDocStatics: Void .ctor() FSharp.Compiler.XmlDoc+XmlDocStatics: XmlDoc Empty FSharp.Compiler.XmlDoc+XmlDocStatics: XmlDoc get_Empty() diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index 9cd1423c6e3..25e45e1d9ee 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -41875,25 +41875,27 @@ FSharp.Compiler.XmlDoc+XmlDoc: Boolean Equals(System.Object, System.Collections. FSharp.Compiler.XmlDoc+XmlDoc: Boolean Equals(XmlDoc) FSharp.Compiler.XmlDoc+XmlDoc: Boolean NonEmpty FSharp.Compiler.XmlDoc+XmlDoc: Boolean get_NonEmpty() -FSharp.Compiler.XmlDoc+XmlDoc: Int32 CompareTo(System.Object) -FSharp.Compiler.XmlDoc+XmlDoc: Int32 CompareTo(System.Object, System.Collections.IComparer) -FSharp.Compiler.XmlDoc+XmlDoc: Int32 CompareTo(XmlDoc) FSharp.Compiler.XmlDoc+XmlDoc: Int32 GetHashCode() FSharp.Compiler.XmlDoc+XmlDoc: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.XmlDoc+XmlDoc: Int32 Tag FSharp.Compiler.XmlDoc+XmlDoc: Int32 get_Tag() FSharp.Compiler.XmlDoc+XmlDoc: System.String ToString() -FSharp.Compiler.XmlDoc+XmlDoc: System.String[] Item -FSharp.Compiler.XmlDoc+XmlDoc: System.String[] get_Item() FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc Empty FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc Merge(XmlDoc, XmlDoc) -FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc NewXmlDoc(System.String[]) FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc Process(XmlDoc) FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc get_Empty() -FSharp.Compiler.XmlDoc+XmlDocCollector: System.String[] LinesBefore(pos) +FSharp.Compiler.XmlDoc+XmlDoc: Boolean IsEmpty +FSharp.Compiler.XmlDoc+XmlDoc: Boolean get_IsEmpty() +FSharp.Compiler.XmlDoc+XmlDoc: System.String GetXmlText() +FSharp.Compiler.XmlDoc+XmlDoc: System.Tuple`2[System.String,FSharp.Compiler.Range+range][] Item +FSharp.Compiler.XmlDoc+XmlDoc: System.Tuple`2[System.String,FSharp.Compiler.Range+range][] get_Item() +FSharp.Compiler.XmlDoc+XmlDoc: XmlDoc NewXmlDoc(System.Tuple`2[System.String,FSharp.Compiler.Range+range][]) +FSharp.Compiler.XmlDoc+XmlDoc: range Range +FSharp.Compiler.XmlDoc+XmlDoc: range get_Range() FSharp.Compiler.XmlDoc+XmlDocCollector: Void .ctor() FSharp.Compiler.XmlDoc+XmlDocCollector: Void AddGrabPoint(pos) -FSharp.Compiler.XmlDoc+XmlDocCollector: Void AddXmlDocLine(System.String, pos) +FSharp.Compiler.XmlDoc+XmlDocCollector: System.Tuple`2[System.String,FSharp.Compiler.Range+range][] LinesBefore(pos) +FSharp.Compiler.XmlDoc+XmlDocCollector: Void AddXmlDocLine(System.String, range) FSharp.Compiler.XmlDoc+XmlDocStatics: Void .ctor() FSharp.Compiler.XmlDoc+XmlDocStatics: XmlDoc Empty FSharp.Compiler.XmlDoc+XmlDocStatics: XmlDoc get_Empty() diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index f63bf89e32b..8080a23b599 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -178,7 +178,7 @@ module rec Compiler = | _ -> failwith message let withOptions (options: string list) (cUnit: CompilationUnit) : CompilationUnit = - withOptionsHelper options "withOptions is only supported n F#" cUnit + withOptionsHelper options "withOptions is only supported for F#" cUnit let withErrorRanges (cUnit: CompilationUnit) : CompilationUnit = withOptionsHelper [ "--test:ErrorRanges" ] "withErrorRanges is only supported on F#" cUnit @@ -195,6 +195,9 @@ module rec Compiler = let withLangVersionPreview (cUnit: CompilationUnit) : CompilationUnit = withOptionsHelper [ "--langversion:preview" ] "withLangVersionPreview is only supported on F#" cUnit + let withXmlCommentChecking (cUnit: CompilationUnit) : CompilationUnit = + withOptionsHelper [ "--warnon:3390" ] "withXmlCommentChecking is only supported for F#" cUnit + let asLibrary (cUnit: CompilationUnit) : CompilationUnit = match cUnit with | FS fs -> FS { fs with OutputType = CompileOutput.Library } @@ -573,7 +576,7 @@ module rec Compiler = let inline checkEqual k a b = if a <> b then - Assert.AreEqual(a, b, sprintf "%s: Mismatch in %s, expected '%A', got '%A'.\nAll errors:\n%A" what k a b errors) + Assert.AreEqual(a, b, sprintf "%s: Mismatch in %s, expected '%A', got '%A'.\nAll errors:\n%A\nExpected errors:\n%A" what k a b errors expected) // TODO: Check all "categories", collect all results and print alltogether. checkEqual "Errors count" expected.Length errors.Length