File: ParseDirectiveArguments.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (97 lines) | stat: -rw-r--r-- 5,128 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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2021 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 Swift project authors
*/

import Markdown

extension BlockDirective {
    /// Attempt to parse directive arguments, emitting parse errors as diagnostics.
    ///
    /// - parameter problems: An `inout` array of `Problem` values to accept directive argument parsing errors.
    func arguments(problems: inout [Problem]) -> [String: Markdown.DirectiveArgument] {
        var parseErrors = [DirectiveArgumentText.ParseError]()
        let parsedArguments = self.argumentText.parseNameValueArguments(parseErrors: &parseErrors)

        problems.append(contentsOf: parseErrors.compactMap { error -> Problem? in
            switch error {
            case let .duplicateArgument(name, firstLocation, duplicateLocation):
                // If we already emitted a diagnostic for the original argument we don't do that a second time.
                // Additionally we search the existing problems in reverse order to find more recent ones faster.
                guard !problems.reversed().contains(where: { problem -> Bool in
                    return problem.diagnostic.identifier == "org.swift.docc.Directive.DuplicateArgument" && problem.diagnostic.range?.lowerBound == firstLocation
                }) else {
                    return nil
                }
                return Problem(
                    diagnostic: Diagnostic(
                        source: duplicateLocation.source,
                        severity: .warning,
                        range: duplicateLocation..<duplicateLocation,
                        identifier: "org.swift.docc.Directive.DuplicateArgument",
                        summary: "Duplicate argument for \(name.singleQuoted)"
                    ),
                    possibleSolutions: []
                )
            case let .missingExpectedCharacter(character, location):
                // We search the existing problems in reverse order to find more recent ones faster.
                guard !problems.reversed().contains(where: { problem -> Bool in
                    return problem.diagnostic.identifier == "org.swift.docc.Directive.MissingExpectedCharacter" && problem.diagnostic.range?.lowerBound == location
                }) else {
                    return nil
                }
                return Problem(
                    diagnostic: Diagnostic(
                        source: location.source,
                        severity: .warning,
                        range: location..<location,
                        identifier: "org.swift.docc.Directive.MissingExpectedCharacter",
                        summary: "Missing expected character '\(character)'",
                        explanation: "Arguments that use special characters or spaces should be wrapped in '\"' quotes"
                    ),
                    possibleSolutions: [
                        Solution(summary: "Insert a '\(character) character", replacements: [
                            Replacement(range: location..<location, replacement: String(character))
                        ])
                    ])
            case let .unexpectedCharacter(character, location):
                // We search the existing problems in reverse order to find more recent ones faster.
                guard !problems.reversed().contains(where: { problem -> Bool in
                    return problem.diagnostic.identifier == "org.swift.docc.Directive.UnexpectedCharacter" && problem.diagnostic.range?.lowerBound == location
                }) else {
                    return nil
                }
                return Problem(
                    diagnostic: Diagnostic(
                        source: location.source,
                        severity: .warning,
                        range: location..<location,
                        identifier: "org.swift.docc.Directive.UnexpectedCharacter",
                        summary: "Unexpected character '\(character)'",
                        explanation: "Arguments that use special characters or spaces should be wrapped in '\"' quotes"
                    ), possibleSolutions: [
                        Solution(summary: "Remove the '\(character) character", replacements: [
                            Replacement(range: location..<SourceLocation(line: location.line, column: location.column+1, source: location.source), replacement: "")
                        ])
                    ])
            }
        })

        var arguments = [String: Markdown.DirectiveArgument]()
        for argument in parsedArguments {
            arguments[argument.name] = argument
        }
        return arguments
    }

    /// Attempt to parse directive arguments, discarding parse errors.
    func arguments() -> [String: Markdown.DirectiveArgument] {
        var problems = [Problem]()
        return arguments(problems: &problems)
    }
}