From 2c217995d5692e92107a69f241f92f6f758cf57a Mon Sep 17 00:00:00 2001 From: nojaf Date: Sat, 7 May 2022 12:14:18 +0200 Subject: [PATCH 1/2] Expose FSharpParserDiagnostic from parseFile. --- paket.dependencies | 2 + paket.lock | 4 +- src/Fantomas.Core/CodeFormatterImpl.fs | 4 +- src/Fantomas.FCS/Fantomas.FCS.fsproj | 7 + src/Fantomas.FCS/Parse.fs | 666 ++++++++++++++++++++++++- 5 files changed, 678 insertions(+), 5 deletions(-) diff --git a/paket.dependencies b/paket.dependencies index ae631c9227..14e8af7c97 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -23,6 +23,8 @@ github: fsprojects/fantomas:829faa6ba834f99afed9b4434b3a1680536474b2 src/Fantoma # F# compiler source github: dotnet/fsharp:7de9637f8d7839c2312748dcbbabb4cda7455548 src/fsharp/FSComp.txt +github: dotnet/fsharp:7de9637f8d7839c2312748dcbbabb4cda7455548 src/fsharp/fsi/FSIstrings.txt +github: dotnet/fsharp:7de9637f8d7839c2312748dcbbabb4cda7455548 src/fsharp/FSStrings.resx github: dotnet/fsharp:7de9637f8d7839c2312748dcbbabb4cda7455548 src/fsharp/utils/sformat.fsi github: dotnet/fsharp:7de9637f8d7839c2312748dcbbabb4cda7455548 src/fsharp/utils/sformat.fs github: dotnet/fsharp:7de9637f8d7839c2312748dcbbabb4cda7455548 src/fsharp/sr.fsi diff --git a/paket.lock b/paket.lock index 9a2fbd4e3d..91bae2b639 100644 --- a/paket.lock +++ b/paket.lock @@ -156,7 +156,7 @@ NUGET System.Security.AccessControl (>= 5.0) System.Security.Principal.Windows (>= 5.0) System.Management (6.0) - Microsoft.Win32.Registry (>= 5.0) - restriction: || (&& (== net6.0) (== netstandard2.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.1)) + Microsoft.Win32.Registry (>= 5.0) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.1)) System.CodeDom (>= 6.0) System.Memory (4.5.4) System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= monotouch)) (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (< netstandard1.1)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= xamarinios)) (&& (== net6.0) (>= xamarinmac)) (&& (== net6.0) (>= xamarintvos)) (&& (== net6.0) (>= xamarinwatchos)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) @@ -214,6 +214,8 @@ GITHUB src/fsharp/ErrorLogger.fs (7de9637f8d7839c2312748dcbbabb4cda7455548) src/fsharp/ErrorLogger.fsi (7de9637f8d7839c2312748dcbbabb4cda7455548) src/fsharp/FSComp.txt (7de9637f8d7839c2312748dcbbabb4cda7455548) + src/fsharp/fsi/FSIstrings.txt (7de9637f8d7839c2312748dcbbabb4cda7455548) + src/fsharp/FSStrings.resx (7de9637f8d7839c2312748dcbbabb4cda7455548) src/fsharp/InternalCollections.fs (7de9637f8d7839c2312748dcbbabb4cda7455548) src/fsharp/InternalCollections.fsi (7de9637f8d7839c2312748dcbbabb4cda7455548) src/fsharp/LanguageFeatures.fs (7de9637f8d7839c2312748dcbbabb4cda7455548) diff --git a/src/Fantomas.Core/CodeFormatterImpl.fs b/src/Fantomas.Core/CodeFormatterImpl.fs index 2afd05471b..3ba0693740 100644 --- a/src/Fantomas.Core/CodeFormatterImpl.fs +++ b/src/Fantomas.Core/CodeFormatterImpl.fs @@ -30,7 +30,7 @@ let parse (isSignature: bool) (source: ISourceText) : Async<(ParsedInput * Defin async { let errors = baseDiagnostics - |> List.filter (fun (_, s) -> s = FSharpDiagnosticSeverity.Error) + |> List.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) if not errors.IsEmpty then raise (FormatException $"Parsing failed with errors: %A{baseDiagnostics}\nAnd options: %A{[]}") @@ -48,7 +48,7 @@ let parse (isSignature: bool) (source: ISourceText) : Async<(ParsedInput * Defin let errors = diagnostics - |> List.filter (fun (_, s) -> s = FSharpDiagnosticSeverity.Error) + |> List.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) if not errors.IsEmpty then raise (FormatException $"Parsing failed with errors: %A{diagnostics}\nAnd options: %A{[]}") diff --git a/src/Fantomas.FCS/Fantomas.FCS.fsproj b/src/Fantomas.FCS/Fantomas.FCS.fsproj index dad426ee24..00e83ba4bc 100644 --- a/src/Fantomas.FCS/Fantomas.FCS.fsproj +++ b/src/Fantomas.FCS/Fantomas.FCS.fsproj @@ -18,6 +18,13 @@ FSComp.txt + + FSIstrings.txt + + + FSStrings.resx + FSStrings.resources + ErrorText\sformat.fsi diff --git a/src/Fantomas.FCS/Parse.fs b/src/Fantomas.FCS/Parse.fs index e4f80a6ff4..335a8c386b 100644 --- a/src/Fantomas.FCS/Parse.fs +++ b/src/Fantomas.FCS/Parse.fs @@ -1,6 +1,10 @@ module Fantomas.FCS.Parse open System +open System.Text +open System.Diagnostics +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.DiagnosticMessage open Internal.Utilities open Internal.Utilities.Library open FSharp.Compiler @@ -432,11 +436,656 @@ let private createLexerFunction (defines: string list) lexbuf (errorLogger: Erro (fun _ -> tokenizer.GetToken()) +type FSharpParserDiagnostic = + { Severity: FSharpDiagnosticSeverity + SubCategory: string + Range: range option + // GetDiagnosticNumber from dotnet/fsharp/src/fsharp/CompilerDiagnostics.fs + ErrorNumber: int option + Message: string } + +let private getErrorString key = SR.GetString key + +let private UnexpectedEndOfInputE () = + DeclareResourceString("UnexpectedEndOfInput", "") + +let private OBlockEndSentenceE () = + DeclareResourceString("BlockEndSentence", "") + +let private UnexpectedE () = + DeclareResourceString("Unexpected", "%s") + +let private NONTERM_interactionE () = + DeclareResourceString("NONTERM.interaction", "") + +let private NONTERM_hashDirectiveE () = + DeclareResourceString("NONTERM.hashDirective", "") + +let private NONTERM_fieldDeclE () = + DeclareResourceString("NONTERM.fieldDecl", "") + +let private NONTERM_unionCaseReprE () = + DeclareResourceString("NONTERM.unionCaseRepr", "") + +let private NONTERM_localBindingE () = + DeclareResourceString("NONTERM.localBinding", "") + +let private NONTERM_hardwhiteLetBindingsE () = + DeclareResourceString("NONTERM.hardwhiteLetBindings", "") + +let private NONTERM_classDefnMemberE () = + DeclareResourceString("NONTERM.classDefnMember", "") + +let private NONTERM_defnBindingsE () = + DeclareResourceString("NONTERM.defnBindings", "") + +let private NONTERM_classMemberSpfnE () = + DeclareResourceString("NONTERM.classMemberSpfn", "") + +let private NONTERM_valSpfnE () = + DeclareResourceString("NONTERM.valSpfn", "") + +let private NONTERM_tyconSpfnE () = + DeclareResourceString("NONTERM.tyconSpfn", "") + +let private NONTERM_anonLambdaExprE () = + DeclareResourceString("NONTERM.anonLambdaExpr", "") + +let private NONTERM_attrUnionCaseDeclE () = + DeclareResourceString("NONTERM.attrUnionCaseDecl", "") + +let private NONTERM_cPrototypeE () = + DeclareResourceString("NONTERM.cPrototype", "") + +let private NONTERM_objectImplementationMembersE () = + DeclareResourceString("NONTERM.objectImplementationMembers", "") + +let private NONTERM_ifExprCasesE () = + DeclareResourceString("NONTERM.ifExprCases", "") + +let private NONTERM_openDeclE () = + DeclareResourceString("NONTERM.openDecl", "") + +let private NONTERM_fileModuleSpecE () = + DeclareResourceString("NONTERM.fileModuleSpec", "") + +let private NONTERM_patternClausesE () = + DeclareResourceString("NONTERM.patternClauses", "") + +let private NONTERM_beginEndExprE () = + DeclareResourceString("NONTERM.beginEndExpr", "") + +let private NONTERM_recdExprE () = + DeclareResourceString("NONTERM.recdExpr", "") + +let private NONTERM_tyconDefnE () = + DeclareResourceString("NONTERM.tyconDefn", "") + +let private NONTERM_exconCoreE () = + DeclareResourceString("NONTERM.exconCore", "") + +let private NONTERM_typeNameInfoE () = + DeclareResourceString("NONTERM.typeNameInfo", "") + +let private NONTERM_attributeListE () = + DeclareResourceString("NONTERM.attributeList", "") + +let private NONTERM_quoteExprE () = + DeclareResourceString("NONTERM.quoteExpr", "") + +let private NONTERM_typeConstraintE () = + DeclareResourceString("NONTERM.typeConstraint", "") + +let private NONTERM_Category_ImplementationFileE () = + DeclareResourceString("NONTERM.Category.ImplementationFile", "") + +let private NONTERM_Category_DefinitionE () = + DeclareResourceString("NONTERM.Category.Definition", "") + +let private NONTERM_Category_SignatureFileE () = + DeclareResourceString("NONTERM.Category.SignatureFile", "") + +let private NONTERM_Category_PatternE () = + DeclareResourceString("NONTERM.Category.Pattern", "") + +let private NONTERM_Category_ExprE () = + DeclareResourceString("NONTERM.Category.Expr", "") + +let private NONTERM_Category_TypeE () = + DeclareResourceString("NONTERM.Category.Type", "") + +let private NONTERM_typeArgsActualE () = + DeclareResourceString("NONTERM.typeArgsActual", "") + +let private TokenName1E () = + DeclareResourceString("TokenName1", "%s") + +let private TokenName1TokenName2E () = + DeclareResourceString("TokenName1TokenName2", "%s%s") + +let private TokenName1TokenName2TokenName3E () = + DeclareResourceString("TokenName1TokenName2TokenName3", "%s%s%s") + +let private getSyntaxErrorMessage ctxt = + let ctxt = + unbox> ctxt + + let os = StringBuilder() + + let (|EndOfStructuredConstructToken|_|) token = + match token with + | Parser.TOKEN_ODECLEND + | Parser.TOKEN_OBLOCKSEP + | Parser.TOKEN_OEND + | Parser.TOKEN_ORIGHT_BLOCK_END + | Parser.TOKEN_OBLOCKEND + | Parser.TOKEN_OBLOCKEND_COMING_SOON + | Parser.TOKEN_OBLOCKEND_IS_HERE -> Some() + | _ -> None + + let tokenIdToText tid = + match tid with + | Parser.TOKEN_IDENT -> getErrorString "Parser.TOKEN.IDENT" + | Parser.TOKEN_BIGNUM + | Parser.TOKEN_INT8 + | Parser.TOKEN_UINT8 + | Parser.TOKEN_INT16 + | Parser.TOKEN_UINT16 + | Parser.TOKEN_INT32 + | Parser.TOKEN_UINT32 + | Parser.TOKEN_INT64 + | Parser.TOKEN_UINT64 + | Parser.TOKEN_UNATIVEINT + | Parser.TOKEN_NATIVEINT -> getErrorString "Parser.TOKEN.INT" + | Parser.TOKEN_IEEE32 + | Parser.TOKEN_IEEE64 -> getErrorString "Parser.TOKEN.FLOAT" + | Parser.TOKEN_DECIMAL -> getErrorString "Parser.TOKEN.DECIMAL" + | Parser.TOKEN_CHAR -> getErrorString "Parser.TOKEN.CHAR" + + | Parser.TOKEN_BASE -> getErrorString "Parser.TOKEN.BASE" + | Parser.TOKEN_LPAREN_STAR_RPAREN -> getErrorString "Parser.TOKEN.LPAREN.STAR.RPAREN" + | Parser.TOKEN_DOLLAR -> getErrorString "Parser.TOKEN.DOLLAR" + | Parser.TOKEN_INFIX_STAR_STAR_OP -> getErrorString "Parser.TOKEN.INFIX.STAR.STAR.OP" + | Parser.TOKEN_INFIX_COMPARE_OP -> getErrorString "Parser.TOKEN.INFIX.COMPARE.OP" + | Parser.TOKEN_COLON_GREATER -> getErrorString "Parser.TOKEN.COLON.GREATER" + | Parser.TOKEN_COLON_COLON -> getErrorString "Parser.TOKEN.COLON.COLON" + | Parser.TOKEN_PERCENT_OP -> getErrorString "Parser.TOKEN.PERCENT.OP" + | Parser.TOKEN_INFIX_AT_HAT_OP -> getErrorString "Parser.TOKEN.INFIX.AT.HAT.OP" + | Parser.TOKEN_INFIX_BAR_OP -> getErrorString "Parser.TOKEN.INFIX.BAR.OP" + | Parser.TOKEN_PLUS_MINUS_OP -> getErrorString "Parser.TOKEN.PLUS.MINUS.OP" + | Parser.TOKEN_PREFIX_OP -> getErrorString "Parser.TOKEN.PREFIX.OP" + | Parser.TOKEN_COLON_QMARK_GREATER -> getErrorString "Parser.TOKEN.COLON.QMARK.GREATER" + | Parser.TOKEN_INFIX_STAR_DIV_MOD_OP -> getErrorString "Parser.TOKEN.INFIX.STAR.DIV.MOD.OP" + | Parser.TOKEN_INFIX_AMP_OP -> getErrorString "Parser.TOKEN.INFIX.AMP.OP" + | Parser.TOKEN_AMP -> getErrorString "Parser.TOKEN.AMP" + | Parser.TOKEN_AMP_AMP -> getErrorString "Parser.TOKEN.AMP.AMP" + | Parser.TOKEN_BAR_BAR -> getErrorString "Parser.TOKEN.BAR.BAR" + | Parser.TOKEN_LESS -> getErrorString "Parser.TOKEN.LESS" + | Parser.TOKEN_GREATER -> getErrorString "Parser.TOKEN.GREATER" + | Parser.TOKEN_QMARK -> getErrorString "Parser.TOKEN.QMARK" + | Parser.TOKEN_QMARK_QMARK -> getErrorString "Parser.TOKEN.QMARK.QMARK" + | Parser.TOKEN_COLON_QMARK -> getErrorString "Parser.TOKEN.COLON.QMARK" + | Parser.TOKEN_INT32_DOT_DOT -> getErrorString "Parser.TOKEN.INT32.DOT.DOT" + | Parser.TOKEN_DOT_DOT -> getErrorString "Parser.TOKEN.DOT.DOT" + | Parser.TOKEN_DOT_DOT_HAT -> getErrorString "Parser.TOKEN.DOT.DOT" + | Parser.TOKEN_QUOTE -> getErrorString "Parser.TOKEN.QUOTE" + | Parser.TOKEN_STAR -> getErrorString "Parser.TOKEN.STAR" + | Parser.TOKEN_HIGH_PRECEDENCE_TYAPP -> getErrorString "Parser.TOKEN.HIGH.PRECEDENCE.TYAPP" + | Parser.TOKEN_COLON -> getErrorString "Parser.TOKEN.COLON" + | Parser.TOKEN_COLON_EQUALS -> getErrorString "Parser.TOKEN.COLON.EQUALS" + | Parser.TOKEN_LARROW -> getErrorString "Parser.TOKEN.LARROW" + | Parser.TOKEN_EQUALS -> getErrorString "Parser.TOKEN.EQUALS" + | Parser.TOKEN_GREATER_BAR_RBRACK -> getErrorString "Parser.TOKEN.GREATER.BAR.RBRACK" + | Parser.TOKEN_MINUS -> getErrorString "Parser.TOKEN.MINUS" + | Parser.TOKEN_ADJACENT_PREFIX_OP -> getErrorString "Parser.TOKEN.ADJACENT.PREFIX.OP" + | Parser.TOKEN_FUNKY_OPERATOR_NAME -> getErrorString "Parser.TOKEN.FUNKY.OPERATOR.NAME" + | Parser.TOKEN_COMMA -> getErrorString "Parser.TOKEN.COMMA" + | Parser.TOKEN_DOT -> getErrorString "Parser.TOKEN.DOT" + | Parser.TOKEN_BAR -> getErrorString "Parser.TOKEN.BAR" + | Parser.TOKEN_HASH -> getErrorString "Parser.TOKEN.HASH" + | Parser.TOKEN_UNDERSCORE -> getErrorString "Parser.TOKEN.UNDERSCORE" + | Parser.TOKEN_SEMICOLON -> getErrorString "Parser.TOKEN.SEMICOLON" + | Parser.TOKEN_SEMICOLON_SEMICOLON -> getErrorString "Parser.TOKEN.SEMICOLON.SEMICOLON" + | Parser.TOKEN_LPAREN -> getErrorString "Parser.TOKEN.LPAREN" + | Parser.TOKEN_RPAREN + | Parser.TOKEN_RPAREN_COMING_SOON + | Parser.TOKEN_RPAREN_IS_HERE -> getErrorString "Parser.TOKEN.RPAREN" + | Parser.TOKEN_LQUOTE -> getErrorString "Parser.TOKEN.LQUOTE" + | Parser.TOKEN_LBRACK -> getErrorString "Parser.TOKEN.LBRACK" + | Parser.TOKEN_LBRACE_BAR -> getErrorString "Parser.TOKEN.LBRACE.BAR" + | Parser.TOKEN_LBRACK_BAR -> getErrorString "Parser.TOKEN.LBRACK.BAR" + | Parser.TOKEN_LBRACK_LESS -> getErrorString "Parser.TOKEN.LBRACK.LESS" + | Parser.TOKEN_LBRACE -> getErrorString "Parser.TOKEN.LBRACE" + | Parser.TOKEN_BAR_RBRACK -> getErrorString "Parser.TOKEN.BAR.RBRACK" + | Parser.TOKEN_BAR_RBRACE -> getErrorString "Parser.TOKEN.BAR.RBRACE" + | Parser.TOKEN_GREATER_RBRACK -> getErrorString "Parser.TOKEN.GREATER.RBRACK" + | Parser.TOKEN_RQUOTE_DOT _ + | Parser.TOKEN_RQUOTE -> getErrorString "Parser.TOKEN.RQUOTE" + | Parser.TOKEN_RBRACK -> getErrorString "Parser.TOKEN.RBRACK" + | Parser.TOKEN_RBRACE + | Parser.TOKEN_RBRACE_COMING_SOON + | Parser.TOKEN_RBRACE_IS_HERE -> getErrorString "Parser.TOKEN.RBRACE" + | Parser.TOKEN_PUBLIC -> getErrorString "Parser.TOKEN.PUBLIC" + | Parser.TOKEN_PRIVATE -> getErrorString "Parser.TOKEN.PRIVATE" + | Parser.TOKEN_INTERNAL -> getErrorString "Parser.TOKEN.INTERNAL" + | Parser.TOKEN_CONSTRAINT -> getErrorString "Parser.TOKEN.CONSTRAINT" + | Parser.TOKEN_INSTANCE -> getErrorString "Parser.TOKEN.INSTANCE" + | Parser.TOKEN_DELEGATE -> getErrorString "Parser.TOKEN.DELEGATE" + | Parser.TOKEN_INHERIT -> getErrorString "Parser.TOKEN.INHERIT" + | Parser.TOKEN_CONSTRUCTOR -> getErrorString "Parser.TOKEN.CONSTRUCTOR" + | Parser.TOKEN_DEFAULT -> getErrorString "Parser.TOKEN.DEFAULT" + | Parser.TOKEN_OVERRIDE -> getErrorString "Parser.TOKEN.OVERRIDE" + | Parser.TOKEN_ABSTRACT -> getErrorString "Parser.TOKEN.ABSTRACT" + | Parser.TOKEN_CLASS -> getErrorString "Parser.TOKEN.CLASS" + | Parser.TOKEN_MEMBER -> getErrorString "Parser.TOKEN.MEMBER" + | Parser.TOKEN_STATIC -> getErrorString "Parser.TOKEN.STATIC" + | Parser.TOKEN_NAMESPACE -> getErrorString "Parser.TOKEN.NAMESPACE" + | Parser.TOKEN_OBLOCKBEGIN -> getErrorString "Parser.TOKEN.OBLOCKBEGIN" + | EndOfStructuredConstructToken -> getErrorString "Parser.TOKEN.OBLOCKEND" + | Parser.TOKEN_THEN + | Parser.TOKEN_OTHEN -> getErrorString "Parser.TOKEN.OTHEN" + | Parser.TOKEN_ELSE + | Parser.TOKEN_OELSE -> getErrorString "Parser.TOKEN.OELSE" + | Parser.TOKEN_LET _ + | Parser.TOKEN_OLET _ -> getErrorString "Parser.TOKEN.OLET" + | Parser.TOKEN_OBINDER + | Parser.TOKEN_BINDER -> getErrorString "Parser.TOKEN.BINDER" + | Parser.TOKEN_OAND_BANG + | Parser.TOKEN_AND_BANG -> getErrorString "Parser.TOKEN.AND.BANG" + | Parser.TOKEN_ODO -> getErrorString "Parser.TOKEN.ODO" + | Parser.TOKEN_OWITH -> getErrorString "Parser.TOKEN.OWITH" + | Parser.TOKEN_OFUNCTION -> getErrorString "Parser.TOKEN.OFUNCTION" + | Parser.TOKEN_OFUN -> getErrorString "Parser.TOKEN.OFUN" + | Parser.TOKEN_ORESET -> getErrorString "Parser.TOKEN.ORESET" + | Parser.TOKEN_ODUMMY -> getErrorString "Parser.TOKEN.ODUMMY" + | Parser.TOKEN_DO_BANG + | Parser.TOKEN_ODO_BANG -> getErrorString "Parser.TOKEN.ODO.BANG" + | Parser.TOKEN_YIELD -> getErrorString "Parser.TOKEN.YIELD" + | Parser.TOKEN_YIELD_BANG -> getErrorString "Parser.TOKEN.YIELD.BANG" + | Parser.TOKEN_OINTERFACE_MEMBER -> getErrorString "Parser.TOKEN.OINTERFACE.MEMBER" + | Parser.TOKEN_ELIF -> getErrorString "Parser.TOKEN.ELIF" + | Parser.TOKEN_RARROW -> getErrorString "Parser.TOKEN.RARROW" + | Parser.TOKEN_SIG -> getErrorString "Parser.TOKEN.SIG" + | Parser.TOKEN_STRUCT -> getErrorString "Parser.TOKEN.STRUCT" + | Parser.TOKEN_UPCAST -> getErrorString "Parser.TOKEN.UPCAST" + | Parser.TOKEN_DOWNCAST -> getErrorString "Parser.TOKEN.DOWNCAST" + | Parser.TOKEN_NULL -> getErrorString "Parser.TOKEN.NULL" + | Parser.TOKEN_RESERVED -> getErrorString "Parser.TOKEN.RESERVED" + | Parser.TOKEN_MODULE + | Parser.TOKEN_MODULE_COMING_SOON + | Parser.TOKEN_MODULE_IS_HERE -> getErrorString "Parser.TOKEN.MODULE" + | Parser.TOKEN_AND -> getErrorString "Parser.TOKEN.AND" + | Parser.TOKEN_AS -> getErrorString "Parser.TOKEN.AS" + | Parser.TOKEN_ASSERT -> getErrorString "Parser.TOKEN.ASSERT" + | Parser.TOKEN_OASSERT -> getErrorString "Parser.TOKEN.ASSERT" + | Parser.TOKEN_ASR -> getErrorString "Parser.TOKEN.ASR" + | Parser.TOKEN_DOWNTO -> getErrorString "Parser.TOKEN.DOWNTO" + | Parser.TOKEN_EXCEPTION -> getErrorString "Parser.TOKEN.EXCEPTION" + | Parser.TOKEN_FALSE -> getErrorString "Parser.TOKEN.FALSE" + | Parser.TOKEN_FOR -> getErrorString "Parser.TOKEN.FOR" + | Parser.TOKEN_FUN -> getErrorString "Parser.TOKEN.FUN" + | Parser.TOKEN_FUNCTION -> getErrorString "Parser.TOKEN.FUNCTION" + | Parser.TOKEN_FINALLY -> getErrorString "Parser.TOKEN.FINALLY" + | Parser.TOKEN_LAZY -> getErrorString "Parser.TOKEN.LAZY" + | Parser.TOKEN_OLAZY -> getErrorString "Parser.TOKEN.LAZY" + | Parser.TOKEN_MATCH -> getErrorString "Parser.TOKEN.MATCH" + | Parser.TOKEN_MATCH_BANG -> getErrorString "Parser.TOKEN.MATCH.BANG" + | Parser.TOKEN_MUTABLE -> getErrorString "Parser.TOKEN.MUTABLE" + | Parser.TOKEN_NEW -> getErrorString "Parser.TOKEN.NEW" + | Parser.TOKEN_OF -> getErrorString "Parser.TOKEN.OF" + | Parser.TOKEN_OPEN -> getErrorString "Parser.TOKEN.OPEN" + | Parser.TOKEN_OR -> getErrorString "Parser.TOKEN.OR" + | Parser.TOKEN_VOID -> getErrorString "Parser.TOKEN.VOID" + | Parser.TOKEN_EXTERN -> getErrorString "Parser.TOKEN.EXTERN" + | Parser.TOKEN_INTERFACE -> getErrorString "Parser.TOKEN.INTERFACE" + | Parser.TOKEN_REC -> getErrorString "Parser.TOKEN.REC" + | Parser.TOKEN_TO -> getErrorString "Parser.TOKEN.TO" + | Parser.TOKEN_TRUE -> getErrorString "Parser.TOKEN.TRUE" + | Parser.TOKEN_TRY -> getErrorString "Parser.TOKEN.TRY" + | Parser.TOKEN_TYPE + | Parser.TOKEN_TYPE_COMING_SOON + | Parser.TOKEN_TYPE_IS_HERE -> getErrorString "Parser.TOKEN.TYPE" + | Parser.TOKEN_VAL -> getErrorString "Parser.TOKEN.VAL" + | Parser.TOKEN_INLINE -> getErrorString "Parser.TOKEN.INLINE" + | Parser.TOKEN_WHEN -> getErrorString "Parser.TOKEN.WHEN" + | Parser.TOKEN_WHILE -> getErrorString "Parser.TOKEN.WHILE" + | Parser.TOKEN_WITH -> getErrorString "Parser.TOKEN.WITH" + | Parser.TOKEN_IF -> getErrorString "Parser.TOKEN.IF" + | Parser.TOKEN_DO -> getErrorString "Parser.TOKEN.DO" + | Parser.TOKEN_GLOBAL -> getErrorString "Parser.TOKEN.GLOBAL" + | Parser.TOKEN_DONE -> getErrorString "Parser.TOKEN.DONE" + | Parser.TOKEN_IN + | Parser.TOKEN_JOIN_IN -> getErrorString "Parser.TOKEN.IN" + | Parser.TOKEN_HIGH_PRECEDENCE_PAREN_APP -> getErrorString "Parser.TOKEN.HIGH.PRECEDENCE.PAREN.APP" + | Parser.TOKEN_HIGH_PRECEDENCE_BRACK_APP -> getErrorString "Parser.TOKEN.HIGH.PRECEDENCE.BRACK.APP" + | Parser.TOKEN_BEGIN -> getErrorString "Parser.TOKEN.BEGIN" + | Parser.TOKEN_END -> getErrorString "Parser.TOKEN.END" + | Parser.TOKEN_HASH_LIGHT + | Parser.TOKEN_HASH_LINE + | Parser.TOKEN_HASH_IF + | Parser.TOKEN_HASH_ELSE + | Parser.TOKEN_HASH_ENDIF -> getErrorString "Parser.TOKEN.HASH.ENDIF" + | Parser.TOKEN_INACTIVECODE -> getErrorString "Parser.TOKEN.INACTIVECODE" + | Parser.TOKEN_LEX_FAILURE -> getErrorString "Parser.TOKEN.LEX.FAILURE" + | Parser.TOKEN_WHITESPACE -> getErrorString "Parser.TOKEN.WHITESPACE" + | Parser.TOKEN_COMMENT -> getErrorString "Parser.TOKEN.COMMENT" + | Parser.TOKEN_LINE_COMMENT -> getErrorString "Parser.TOKEN.LINE.COMMENT" + | Parser.TOKEN_STRING_TEXT -> getErrorString "Parser.TOKEN.STRING.TEXT" + | Parser.TOKEN_BYTEARRAY -> getErrorString "Parser.TOKEN.BYTEARRAY" + | Parser.TOKEN_STRING -> getErrorString "Parser.TOKEN.STRING" + | Parser.TOKEN_KEYWORD_STRING -> getErrorString "Parser.TOKEN.KEYWORD_STRING" + | Parser.TOKEN_EOF -> getErrorString "Parser.TOKEN.EOF" + | Parser.TOKEN_CONST -> getErrorString "Parser.TOKEN.CONST" + | Parser.TOKEN_FIXED -> getErrorString "Parser.TOKEN.FIXED" + | Parser.TOKEN_INTERP_STRING_BEGIN_END -> getErrorString "Parser.TOKEN.INTERP.STRING.BEGIN.END" + | Parser.TOKEN_INTERP_STRING_BEGIN_PART -> getErrorString "Parser.TOKEN.INTERP.STRING.BEGIN.PART" + | Parser.TOKEN_INTERP_STRING_PART -> getErrorString "Parser.TOKEN.INTERP.STRING.PART" + | Parser.TOKEN_INTERP_STRING_END -> getErrorString "Parser.TOKEN.INTERP.STRING.END" + | unknown -> + Debug.Assert(false, "unknown token tag") + let result = $"%+A{unknown}" + Debug.Assert(false, result) + result + + match ctxt.CurrentToken with + | None -> + os.Append(UnexpectedEndOfInputE().Format) + |> ignore + | Some token -> + match (token + |> Parser.tagOfToken + |> Parser.tokenTagToTokenId), + token + with + | EndOfStructuredConstructToken, _ -> os.Append(OBlockEndSentenceE().Format) |> ignore + | Parser.TOKEN_LEX_FAILURE, Parser.LEX_FAILURE str -> Printf.bprintf os $"%s{str}" (* Fix bug://2431 *) + | token, _ -> + os.Append(UnexpectedE().Format(token |> tokenIdToText)) + |> ignore + + (* Search for a state producing a single recognized non-terminal in the states on the stack *) + let foundInContext = + + (* Merge a bunch of expression non terminals *) + let (|NONTERM_Category_Expr|_|) = + function + | Parser.NONTERM_argExpr + | Parser.NONTERM_minusExpr + | Parser.NONTERM_parenExpr + | Parser.NONTERM_atomicExpr + | Parser.NONTERM_appExpr + | Parser.NONTERM_tupleExpr + | Parser.NONTERM_declExpr + | Parser.NONTERM_braceExpr + | Parser.NONTERM_braceBarExpr + | Parser.NONTERM_typedSequentialExprBlock + | Parser.NONTERM_interactiveExpr -> Some() + | _ -> None + + (* Merge a bunch of pattern non terminals *) + let (|NONTERM_Category_Pattern|_|) = + function + | Parser.NONTERM_constrPattern + | Parser.NONTERM_parenPattern + | Parser.NONTERM_atomicPattern -> Some() + | _ -> None + + (* Merge a bunch of if/then/else non terminals *) + let (|NONTERM_Category_IfThenElse|_|) = + function + | Parser.NONTERM_ifExprThen + | Parser.NONTERM_ifExprElifs + | Parser.NONTERM_ifExprCases -> Some() + | _ -> None + + (* Merge a bunch of non terminals *) + let (|NONTERM_Category_SignatureFile|_|) = + function + | Parser.NONTERM_signatureFile + | Parser.NONTERM_moduleSpfn + | Parser.NONTERM_moduleSpfns -> Some() + | _ -> None + + let (|NONTERM_Category_ImplementationFile|_|) = + function + | Parser.NONTERM_implementationFile + | Parser.NONTERM_fileNamespaceImpl + | Parser.NONTERM_fileNamespaceImpls -> Some() + | _ -> None + + let (|NONTERM_Category_Definition|_|) = + function + | Parser.NONTERM_fileModuleImpl + | Parser.NONTERM_moduleDefn + | Parser.NONTERM_interactiveDefns + | Parser.NONTERM_moduleDefns + | Parser.NONTERM_moduleDefnsOrExpr -> Some() + | _ -> None + + let (|NONTERM_Category_Type|_|) = + function + | Parser.NONTERM_typ + | Parser.NONTERM_tupleType -> Some() + | _ -> None + + let (|NONTERM_Category_Interaction|_|) = + function + | Parser.NONTERM_interactiveItemsTerminator + | Parser.NONTERM_interaction + | Parser.NONTERM__startinteraction -> Some() + | _ -> None + + + // Canonicalize the categories and check for a unique category + ctxt.ReducibleProductions + |> List.exists (fun prods -> + match prods + |> List.map Parser.prodIdxToNonTerminal + |> List.map (function + | NONTERM_Category_Type -> Parser.NONTERM_typ + | NONTERM_Category_Expr -> Parser.NONTERM_declExpr + | NONTERM_Category_Pattern -> Parser.NONTERM_atomicPattern + | NONTERM_Category_IfThenElse -> Parser.NONTERM_ifExprThen + | NONTERM_Category_SignatureFile -> Parser.NONTERM_signatureFile + | NONTERM_Category_ImplementationFile -> Parser.NONTERM_implementationFile + | NONTERM_Category_Definition -> Parser.NONTERM_moduleDefn + | NONTERM_Category_Interaction -> Parser.NONTERM_interaction + | nt -> nt) + |> Set.ofList + |> Set.toList + with + | [ Parser.NONTERM_interaction ] -> + os.Append(NONTERM_interactionE().Format) |> ignore + true + | [ Parser.NONTERM_hashDirective ] -> + os.Append(NONTERM_hashDirectiveE().Format) + |> ignore + + true + | [ Parser.NONTERM_fieldDecl ] -> + os.Append(NONTERM_fieldDeclE().Format) |> ignore + true + | [ Parser.NONTERM_unionCaseRepr ] -> + os.Append(NONTERM_unionCaseReprE().Format) + |> ignore + + true + | [ Parser.NONTERM_localBinding ] -> + os.Append(NONTERM_localBindingE().Format) + |> ignore + + true + | [ Parser.NONTERM_hardwhiteLetBindings ] -> + os.Append(NONTERM_hardwhiteLetBindingsE().Format) + |> ignore + + true + | [ Parser.NONTERM_classDefnMember ] -> + os.Append(NONTERM_classDefnMemberE().Format) + |> ignore + + true + | [ Parser.NONTERM_defnBindings ] -> + os.Append(NONTERM_defnBindingsE().Format) + |> ignore + + true + | [ Parser.NONTERM_classMemberSpfn ] -> + os.Append(NONTERM_classMemberSpfnE().Format) + |> ignore + + true + | [ Parser.NONTERM_valSpfn ] -> + os.Append(NONTERM_valSpfnE().Format) |> ignore + true + | [ Parser.NONTERM_tyconSpfn ] -> + os.Append(NONTERM_tyconSpfnE().Format) |> ignore + true + | [ Parser.NONTERM_anonLambdaExpr ] -> + os.Append(NONTERM_anonLambdaExprE().Format) + |> ignore + + true + | [ Parser.NONTERM_attrUnionCaseDecl ] -> + os.Append(NONTERM_attrUnionCaseDeclE().Format) + |> ignore + + true + | [ Parser.NONTERM_cPrototype ] -> + os.Append(NONTERM_cPrototypeE().Format) |> ignore + true + | [ Parser.NONTERM_objExpr | Parser.NONTERM_objectImplementationMembers ] -> + os.Append(NONTERM_objectImplementationMembersE().Format) + |> ignore + + true + | [ Parser.NONTERM_ifExprThen | Parser.NONTERM_ifExprElifs | Parser.NONTERM_ifExprCases ] -> + os.Append(NONTERM_ifExprCasesE().Format) |> ignore + true + | [ Parser.NONTERM_openDecl ] -> + os.Append(NONTERM_openDeclE().Format) |> ignore + true + | [ Parser.NONTERM_fileModuleSpec ] -> + os.Append(NONTERM_fileModuleSpecE().Format) + |> ignore + + true + | [ Parser.NONTERM_patternClauses ] -> + os.Append(NONTERM_patternClausesE().Format) + |> ignore + + true + | [ Parser.NONTERM_beginEndExpr ] -> + os.Append(NONTERM_beginEndExprE().Format) + |> ignore + + true + | [ Parser.NONTERM_recdExpr ] -> + os.Append(NONTERM_recdExprE().Format) |> ignore + true + | [ Parser.NONTERM_tyconDefn ] -> + os.Append(NONTERM_tyconDefnE().Format) |> ignore + true + | [ Parser.NONTERM_exconCore ] -> + os.Append(NONTERM_exconCoreE().Format) |> ignore + true + | [ Parser.NONTERM_typeNameInfo ] -> + os.Append(NONTERM_typeNameInfoE().Format) + |> ignore + + true + | [ Parser.NONTERM_attributeList ] -> + os.Append(NONTERM_attributeListE().Format) + |> ignore + + true + | [ Parser.NONTERM_quoteExpr ] -> + os.Append(NONTERM_quoteExprE().Format) |> ignore + true + | [ Parser.NONTERM_typeConstraint ] -> + os.Append(NONTERM_typeConstraintE().Format) + |> ignore + + true + | [ NONTERM_Category_ImplementationFile ] -> + os.Append(NONTERM_Category_ImplementationFileE().Format) + |> ignore + + true + | [ NONTERM_Category_Definition ] -> + os.Append(NONTERM_Category_DefinitionE().Format) + |> ignore + + true + | [ NONTERM_Category_SignatureFile ] -> + os.Append(NONTERM_Category_SignatureFileE().Format) + |> ignore + + true + | [ NONTERM_Category_Pattern ] -> + os.Append(NONTERM_Category_PatternE().Format) + |> ignore + + true + | [ NONTERM_Category_Expr ] -> + os.Append(NONTERM_Category_ExprE().Format) + |> ignore + + true + | [ NONTERM_Category_Type ] -> + os.Append(NONTERM_Category_TypeE().Format) + |> ignore + + true + | [ Parser.NONTERM_typeArgsActual ] -> + os.Append(NONTERM_typeArgsActualE().Format) + |> ignore + + true + | _ -> false) + +#if DEBUG + if not foundInContext then + Printf.bprintf + os + $". (no 'in' context found: %+A{List.map (List.map Parser.prodIdxToNonTerminal) ctxt.ReducibleProductions})" +#else + foundInContext |> ignore // suppress unused variable warning in RELEASE +#endif + let fix (s: string) = + s + .Replace(SR.GetString("FixKeyword"), "") + .Replace(SR.GetString("FixSymbol"), "") + .Replace(SR.GetString("FixReplace"), "") + + match (ctxt.ShiftTokens + |> List.map Parser.tokenTagToTokenId + |> List.filter (function + | Parser.TOKEN_error + | Parser.TOKEN_EOF -> false + | _ -> true) + |> List.map tokenIdToText + |> Set.ofList + |> Set.toList) + with + | [ tokenName1 ] -> + os.Append(TokenName1E().Format(fix tokenName1)) + |> ignore + | [ tokenName1; tokenName2 ] -> + os.Append(TokenName1TokenName2E().Format (fix tokenName1) (fix tokenName2)) + |> ignore + | [ tokenName1; tokenName2; tokenName3 ] -> + os.Append(TokenName1TokenName2TokenName3E().Format (fix tokenName1) (fix tokenName2) (fix tokenName3)) + |> ignore + | _ -> () + + os.ToString() + let parseFile (isSignature: bool) (sourceText: ISourceText) (defines: string list) - : ParsedInput * (exn * Diagnostics.FSharpDiagnosticSeverity) list = + : ParsedInput * FSharpParserDiagnostic list = let errorLogger = CapturingErrorLogger("ErrorHandler") let parseResult = @@ -461,6 +1110,19 @@ let parseFile EmptyParsedInput(fileName, (isLastCompiland, isExe))) let diagnostics = - List.map (fun (p, severity) -> p.Exception, severity) errorLogger.Diagnostics + List.map + (fun (p, severity) -> + let range, message, errorNumber = + match p.Exception with + | :? IndentationProblem as ip -> Some ip.Data1, ip.Data0, Some 58 + | :? SyntaxError as se -> Some se.range, (getSyntaxErrorMessage se.Data0), Some 10 + | _ -> None, p.Exception.Message, None + + { Severity = severity + SubCategory = "parse" + Range = range + ErrorNumber = errorNumber + Message = message }) + errorLogger.Diagnostics parseResult, diagnostics From ba5e070a7aa82900311d91d1429a1c9a576d649d Mon Sep 17 00:00:00 2001 From: nojaf Date: Sat, 7 May 2022 12:16:02 +0200 Subject: [PATCH 2/2] Add changelog entry. --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f408398554..b2b3bdc1bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [5.0.0-alpha-004] - 2022-05-07 + +### Changed +* FCS: Expose FSharpParserDiagnostic from parseFile. [https://github.com/fsprojects/fantomas/pull/2233](2233) + ## [5.0.0-alpha-003] - 2022-05-06 ### Changed