Skip to content

F# multi-line strings do not preserve line state #353

@rdipardo

Description

@rdipardo

LexFSharp does not ensure the per-line stability of quoted string literals within the span of multi-line strings, such as the XML attributes in this example:

"""<?xml version="1.0" encoding="utf-8"?>
<root>
  <pre xml:space="preserve">

  </pre>
</root>
"""

After the first newline, the lexer loses track of the enclosing string's style, transitioning to the default state as soon as a double quote is encountered:

Visual Styles

gscite.561.fsharp.raw.str.literals

(Example) Diagnostic Output

~/git/lexilla/lexilla/test/examples/fsharp/quoted.fsx:3: has different per-line styles

This patch refactors string lexing to preserve line state of multi-line strings, both verbatim and interpolated:

0001-gh-353-fsharp-refactor-multi-line-strings.patch.txt

Significant changes include:

  • removal of the FSharpString structure; its properties are now saved in the upper bits of the line state integer

  • removal of the CanEmbedQuotes helper function; its content has been inlined at the call site

  • treating quoted identifiers (delimited by ``) as a separate case from strings; this was always more logical as quoted identifiers cannot span lines:

    Microsoft (R) F# Interactive version 15.2.201.0 for F# 10.0
    Copyright (c) Microsoft Corporation. All Rights Reserved.
    
    For help type #help;;
    
    > let ``name with " "s
    
      let ``name with " "s
      ----^^^^^^^^^^^^^^^^
    
    stdin(1,5): error FS3563: This is not a valid identifier
    
    - ;;
    > let ``better name with " "s`` = ()
    - ;;
    val ``better name with " "s`` : unit = ()
    

Since the affected code paths include format specifier handling, new examples have been added to the suite of interpolated strings, where any regressions in single-line string lexing are most likely to be noticed:

0002-gh-353-fsharp-test-multi-line-strings.patch.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    committedIssue fixed in repository but not in releasefsharpCaused by the fsharp (F#) lexer

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions