fix closure of last <File> in result xml file and add contribution message
[scilab.git] / scilab / modules / slint / src / cpp / SLintXmlResult.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include <string>
17
18 #include "output/SLintXmlResult.hxx"
19 #include "checkers/SLintChecker.hxx"
20 #include "FileException.hxx"
21 #include "SLint.hxx"
22 #include "SciFile.hxx"
23 #include "UTF8.hxx"
24
25 extern "C"
26 {
27 #include "sci_malloc.h"
28 #include "charEncoding.h"
29 #include "localization.h"
30 }
31
32 namespace slint
33 {
34
35 SLintXmlResult::SLintXmlResult(const std::wstring & _path) : current(nullptr), path(_path)
36 {
37     const std::wstring fullpath = SLint::getFullPath(path);
38     out = new std::ofstream(scilab::UTF8::toUTF8(fullpath), std::ios::out);
39     if (!out->is_open())
40     {
41         delete out;
42         out = nullptr;
43         throw FileException(fullpath, L"Can\'t open it.");
44     }
45     else
46     {
47         (*out) << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
48             << "<SLintResult>\n";
49     }
50 }
51
52 SLintXmlResult::~SLintXmlResult()
53 {
54     if (out)
55     {
56         out->close();
57         delete out;
58     }
59 }
60
61 void SLintXmlResult::finalize()
62 {
63     if (current.get())
64     {
65         (*out) << "  </File>\n";
66     }
67
68     (*out) << "</SLintResult>\n";
69     out->close();
70     delete out;
71     out = nullptr;
72 }
73
74 const std::string SLintXmlResult::getStr(const std::wstring & str)
75 {
76     return scilab::UTF8::toUTF8(replaceByEntities(str));
77 }
78
79 void SLintXmlResult::handleMessage(SLintContext & context, const Location & loc, const SLintChecker & checker, const unsigned sub, const std::wstring & msg)
80 {
81     if (context.getSciFile().get() != current.get())
82     {
83         if (current.get())
84         {
85             (*out) << "  </File>\n";
86         }
87         current = context.getSciFile();
88         print(current);
89     }
90     print(loc, checker, sub, msg);
91 }
92
93 void SLintXmlResult::print(const SciFilePtr & file)
94 {
95     (*out) << "  <File name=\"" << getStr(file->getFilename()) << "\">\n";
96 }
97
98 void SLintXmlResult::print(const Location & loc, const SLintChecker & checker, const unsigned sub, const std::wstring & msg)
99 {
100     (*out) << "    <Result>\n";
101     print(loc);
102     print(checker, sub);
103     print(msg);
104     (*out) << "    </Result>\n";
105 }
106
107 void SLintXmlResult::print(const Location & loc)
108 {
109     (*out) << "      <Location first_line=\"" << loc.first_line
110         << "\" first_column=\"" << loc.first_column
111         << "\" last_line=\"" << loc.last_line
112         << "\" last_column=\"" << loc.last_column
113         << "\"/>\n";
114 }
115
116 void SLintXmlResult::print(const SLintChecker & checker, const unsigned sub)
117 {
118     (*out) << "      <Checker name=\"" << checker.getName()
119         << "\" id=\"" << getStr(checker.getId(sub))
120         << "\"/>\n";
121 }
122
123 void SLintXmlResult::print(const std::wstring & msg)
124 {
125     (*out) << "      <Message text=\"" << getStr(msg)
126         << "\"/>\n";
127 }
128
129 std::wstring SLintXmlResult::replaceByEntities(const std::wstring & seq)
130 {
131     std::vector<wchar_t> buf;
132     for (auto c : seq)
133     {
134         if (c == L'<')
135         {
136             pushEntity(buf, L"&lt;", 4);
137         }
138         else if (c == L'>')
139         {
140             pushEntity(buf, L"&gt;", 4);
141         }
142         else if (c == L'\'')
143         {
144             pushEntity(buf, L"&apos;", 6);
145         }
146         else if (c == L'\"')
147         {
148             pushEntity(buf, L"&quot;", 6);
149         }
150         else if (c == L'&')
151         {
152             pushEntity(buf, L"&amp;", 5);
153         }
154         else
155         {
156             buf.push_back(c);
157         }
158     }
159
160     return std::wstring(buf.begin(), buf.end());
161 }
162
163 } // namespace slint