File: Parsing.swift

package info (click to toggle)
swiftlang 6.2.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,856,264 kB
  • sloc: cpp: 9,995,718; ansic: 2,234,019; asm: 1,092,167; python: 313,940; objc: 82,726; f90: 80,126; lisp: 38,373; pascal: 25,580; sh: 20,378; ml: 5,058; perl: 4,751; makefile: 4,725; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (79 lines) | stat: -rw-r--r-- 3,510 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Foundation
import SwiftDiagnostics
import SwiftOperators
@_spi(ExperimentalLanguageFeatures) import SwiftParser
import SwiftParserDiagnostics
import SwiftSyntax

/// Parses the given source code and returns a valid `SourceFileSyntax` node.
///
/// This helper function automatically folds sequence expressions using the given operator table,
/// ignoring errors so that formatting can do something reasonable in the presence of unrecognized
/// operators.
///
/// - Parameters:
///   - source: The Swift source code to be formatted.
///   - operatorTable: The operator table to use for sequence folding.
///   - url: A file URL denoting the filename/path that should be assumed for this syntax tree,
///     which is associated with any diagnostics emitted during formatting. If this is nil, a
///     dummy value will be used.
///   - experimentalFeatures: The set of experimental features that should be enabled in the parser.
///     These names must be from the set of parser-recognized experimental language features in
///     `SwiftParser`'s `Parser.ExperimentalFeatures` enum, which match the spelling defined in the
///     compiler's `Features.def` file.
///   - parsingDiagnosticHandler: An optional callback that will be notified if there are any
///     errors when parsing the source code.
/// - Throws: If an unrecoverable error occurs when formatting the code.
func parseAndEmitDiagnostics(
  source: String,
  operatorTable: OperatorTable,
  assumingFileURL url: URL?,
  experimentalFeatures: Set<String>,
  parsingDiagnosticHandler: ((Diagnostic, SourceLocation) -> Void)? = nil
) throws -> SourceFileSyntax {
  var experimentalFeaturesSet: Parser.ExperimentalFeatures = []
  for featureName in experimentalFeatures {
    guard let featureValue = Parser.ExperimentalFeatures(name: featureName) else {
      throw SwiftFormatError.unrecognizedExperimentalFeature(featureName)
    }
    experimentalFeaturesSet.formUnion(featureValue)
  }
  var source = source
  let sourceFile = source.withUTF8 { sourceBytes in
    operatorTable.foldAll(Parser.parse(source: sourceBytes, experimentalFeatures: experimentalFeaturesSet)) { _ in }
      .as(SourceFileSyntax.self)!
  }
  let diagnostics = ParseDiagnosticsGenerator.diagnostics(for: sourceFile)
  var hasErrors = false
  if let parsingDiagnosticHandler = parsingDiagnosticHandler {
    let expectedConverter =
      SourceLocationConverter(fileName: url?.path ?? "<unknown>", tree: sourceFile)
    for diagnostic in diagnostics {
      let location = diagnostic.location(converter: expectedConverter)

      // Ignore editor placeholders, because it is useful to support formatting
      // in-progress files that contain those.
      if diagnostic.diagnosticID != StaticTokenError.editorPlaceholder.diagnosticID {
        parsingDiagnosticHandler(diagnostic, location)
        hasErrors = true
      }
    }
  }

  guard !hasErrors else {
    throw SwiftFormatError.fileContainsInvalidSyntax
  }
  return sourceFile
}