1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Yaml\Exception;
13
14/**
15 * Exception class thrown when an error occurs during parsing.
16 *
17 * @author Fabien Potencier <fabien@symfony.com>
18 */
19class ParseException extends RuntimeException
20{
21    private $parsedFile;
22    private $parsedLine;
23    private $snippet;
24    private $rawMessage;
25
26    /**
27     * @param string      $message    The error message
28     * @param int         $parsedLine The line where the error occurred
29     * @param string|null $snippet    The snippet of code near the problem
30     * @param string|null $parsedFile The file name where the error occurred
31     */
32    public function __construct(string $message, int $parsedLine = -1, string $snippet = null, string $parsedFile = null, \Throwable $previous = null)
33    {
34        $this->parsedFile = $parsedFile;
35        $this->parsedLine = $parsedLine;
36        $this->snippet = $snippet;
37        $this->rawMessage = $message;
38
39        $this->updateRepr();
40
41        parent::__construct($this->message, 0, $previous);
42    }
43
44    /**
45     * Gets the snippet of code near the error.
46     *
47     * @return string The snippet of code
48     */
49    public function getSnippet()
50    {
51        return $this->snippet;
52    }
53
54    /**
55     * Sets the snippet of code near the error.
56     *
57     * @param string $snippet The code snippet
58     */
59    public function setSnippet($snippet)
60    {
61        $this->snippet = $snippet;
62
63        $this->updateRepr();
64    }
65
66    /**
67     * Gets the filename where the error occurred.
68     *
69     * This method returns null if a string is parsed.
70     *
71     * @return string The filename
72     */
73    public function getParsedFile()
74    {
75        return $this->parsedFile;
76    }
77
78    /**
79     * Sets the filename where the error occurred.
80     *
81     * @param string $parsedFile The filename
82     */
83    public function setParsedFile($parsedFile)
84    {
85        $this->parsedFile = $parsedFile;
86
87        $this->updateRepr();
88    }
89
90    /**
91     * Gets the line where the error occurred.
92     *
93     * @return int The file line
94     */
95    public function getParsedLine()
96    {
97        return $this->parsedLine;
98    }
99
100    /**
101     * Sets the line where the error occurred.
102     *
103     * @param int $parsedLine The file line
104     */
105    public function setParsedLine($parsedLine)
106    {
107        $this->parsedLine = $parsedLine;
108
109        $this->updateRepr();
110    }
111
112    private function updateRepr()
113    {
114        $this->message = $this->rawMessage;
115
116        $dot = false;
117        if ('.' === substr($this->message, -1)) {
118            $this->message = substr($this->message, 0, -1);
119            $dot = true;
120        }
121
122        if (null !== $this->parsedFile) {
123            $this->message .= sprintf(' in %s', json_encode($this->parsedFile, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
124        }
125
126        if ($this->parsedLine >= 0) {
127            $this->message .= sprintf(' at line %d', $this->parsedLine);
128        }
129
130        if ($this->snippet) {
131            $this->message .= sprintf(' (near "%s")', $this->snippet);
132        }
133
134        if ($dot) {
135            $this->message .= '.';
136        }
137    }
138}
139