Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmldomoutwriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
7#include "qqmldomitem_p.h"
8#include "qqmldomcomments_p.h"
10#include "qqmldomtop_p.h"
11
12#include <QtCore/QLoggingCategory>
13
15namespace QQmlJS {
16namespace Dom {
17
19 : itemCanonicalPath(itCanonicalPath), item(it), currentMap(fLoc)
20{
21 DomItem cRegions = it.field(Fields::comments);
22 if (const RegionComments *cRegionsPtr = cRegions.as<RegionComments>()) {
23 pendingComments = cRegionsPtr->regionComments;
24 fLoc->info().ensureCommentLocations(pendingComments.keys());
25 }
26}
27
29{
30 if (w.lineWriter.options().updateOptions & LineWriterOptions::Update::Locations)
31 w.lineWriter.endSourceLocation(fullRegionId);
32 if (!pendingRegions.isEmpty()) {
33 qCWarning(writeOutLog) << "PendingRegions non empty when closing item"
34 << pendingRegions.keys();
35 auto iend = pendingRegions.end();
36 auto it = pendingRegions.begin();
37 while (it == iend) {
38 w.lineWriter.endSourceLocation(it.value());
39 ++it;
40 }
41 }
42 if (!w.skipComments && !pendingComments.isEmpty())
43 qCWarning(writeOutLog) << "PendingComments when closing item "
44 << item.canonicalPath().toString() << "for regions"
45 << pendingComments.keys();
46}
47
49{
50 return states[states.size() - 1 - i];
51}
52
54{
55 if (!topLocation->path())
56 topLocation->setPath(it.canonicalPath());
59 Path itP = it.canonicalPath();
60 if (updateLocs) {
61 if (!states.isEmpty()
62 && states.last().itemCanonicalPath
63 == itP.mid(0, states.last().itemCanonicalPath.length())) {
64 int oldL = states.last().itemCanonicalPath.length();
65 newFLoc = FileLocations::ensure(states.last().currentMap,
66 itP.mid(oldL, itP.length() - oldL),
68
69 } else {
71 }
72 }
73 states.append(OutWriterState(itP, it, newFLoc));
74 if (updateLocs)
75 state().fullRegionId = lineWriter.startSourceLocation(
76 [newFLoc](SourceLocation l) { FileLocations::updateFullLocation(newFLoc, l); });
78}
79
81{
82 Q_ASSERT(states.size() > 0);
83 Q_ASSERT(state().item == it);
85 state().closeState(*this);
86 states.removeLast();
87}
88
90{
91 Q_ASSERT(!state().pendingRegions.contains(rName));
92 FileLocations::Tree fMap = state().currentMap;
93 if (!skipComments && state().pendingComments.contains(rName)) {
96 (updateLocs ? &(fMap->info().preCommentLocations[rName]) : nullptr);
97 state().pendingComments[rName].writePre(*this, cLocs);
98 }
99 state().pendingRegions[rName] = lineWriter.startSourceLocation(
100 [rName, fMap](SourceLocation l) { FileLocations::addRegion(fMap, rName, l); });
101}
102
104{
105 Q_ASSERT(state().pendingRegions.contains(rName));
106 FileLocations::Tree fMap = state().currentMap;
107 lineWriter.endSourceLocation(state().pendingRegions.value(rName));
108 state().pendingRegions.remove(rName);
109 if (state().pendingComments.contains(rName)) {
110 if (!skipComments) {
111 bool updateLocs =
113 QList<SourceLocation> *cLocs =
114 (updateLocs ? &(fMap->info().postCommentLocations[rName]) : nullptr);
115 state().pendingComments[rName].writePost(*this, cLocs);
116 }
117 state().pendingComments.remove(rName);
118 }
119}
120
122{
123 regionStart(rName);
124 lineWriter.write(toWrite);
125 regionEnd(rName);
126 return *this;
127}
128
130{
132 if (std::shared_ptr<QmlFile> qmlFilePtr = qmlFile.ownerAs<QmlFile>()) {
133 std::shared_ptr<QmlFile> copyPtr = qmlFilePtr->makeCopy(qmlFile);
134 DomItem env = qmlFile.environment();
135 std::shared_ptr<DomEnvironment> envPtr = env.ownerAs<DomEnvironment>();
136 Q_ASSERT(envPtr);
137 auto newEnvPtr = std::make_shared<DomEnvironment>(
138 envPtr, envPtr->loadPaths(), envPtr->options());
139 newEnvPtr->addQmlFile(copyPtr);
140 MutableDomItem copy = MutableDomItem(DomItem(newEnvPtr).copy(copyPtr));
142 Path qmlFilePath = qmlFile.canonicalPath();
143 if (newLoc->path() != qmlFilePath) {
144 if (newLoc->path()) {
145 if (newLoc->path().length() > qmlFilePath.length()
146 && newLoc->path().mid(0, qmlFilePath.length()) == qmlFilePath) {
147 newLoc = FileLocations::createTree(qmlFilePath);
149 FileLocations::ensure(newLoc, newLoc->path().mid(qmlFilePath.length()),
151 loc->setSubItems(topLocation->subItems());
152 } else {
153 qCWarning(writeOutLog)
154 << "failed to base fileLocations in OutWriter (" << newLoc->path()
155 << ") to current file (" << qmlFilePath << ")";
156 }
157 } else {
158 newLoc = FileLocations::createTree(qmlFilePath);
159 Q_ASSERT(newLoc->subItems().isEmpty() && newLoc->info().regions.isEmpty());
160 }
161 }
162 copyPtr->setFileLocationsTree(newLoc);
165 [&copy, qmlFilePath](Path p, UpdatedScriptExpression::Tree t) {
166 if (std::shared_ptr<ScriptExpression> exprPtr = t->info().expr) {
167 Q_ASSERT(p.mid(0, qmlFilePath.length()) == qmlFilePath);
168 MutableDomItem targetExpr = copy.path(p.mid(qmlFilePath.length()));
169 if (!targetExpr)
170 qCWarning(writeOutLog) << "failed to get" << p.mid(qmlFilePath.length())
171 << "from" << copy.canonicalPath();
172 else if (exprPtr->ast()
173 || (!targetExpr.as<ScriptExpression>()
174 || !targetExpr.as<ScriptExpression>()->ast()))
175 targetExpr.setScript(exprPtr);
176 else {
177 qCWarning(writeOutLog).noquote()
178 << "Skipped update of reformatted ScriptExpression with "
179 "code:\n---------------\n"
180 << exprPtr->code() << "\n---------------\n preCode:" <<
181 [exprPtr](Sink s) { sinkEscaped(s, exprPtr->preCode()); }
182 << "\n postCode: " <<
183 [exprPtr](Sink s) { sinkEscaped(s, exprPtr->postCode()); }
184 << "\n as it failed standalone reparse with errors:" <<
185 [&targetExpr, exprPtr](Sink s) {
186 targetExpr.item()
187 .copy(exprPtr, targetExpr.canonicalPath())
188 .iterateErrors(
189 [s](DomItem, ErrorMessage msg) {
190 s(u"\n ");
191 msg.dump(s);
192 return true;
193 },
194 true);
195 }
196 << "\n";
197 }
198 }
199 return true;
200 });
201 return copy.item();
202 }
203 return DomItem();
204}
205
206} // namespace Dom
207} // namespace QQmlJS
Definition qlist.h:74
Represents a consistent set of types organized in modules, it is the top level of the DOM.
std::shared_ptr< T > ownerAs()
InternalKind internalKind() const
static Tree createTree(Path basePath)
static void addRegion(Tree fLoc, QString locName, SourceLocation loc)
static void updateFullLocation(Tree fLoc, SourceLocation loc)
static Tree ensure(Tree base, Path basePath, AttachedInfo::PathType pType=AttachedInfo::PathType::Relative)
std::shared_ptr< AttachedInfoT< FileLocations > > Tree
LineWriter & write(QStringView v, TextAddType tType=TextAddType::Normal)
void endSourceLocation(PendingSourceLocationId)
PendingSourceLocationId startSourceLocation(SourceLocation *)
const LineWriterOptions & options() const
QMap< QString, PendingSourceLocationId > pendingRegions
PendingSourceLocationId fullRegionId
OutWriterState(Path itPath, DomItem &it, FileLocations::Tree fLoc)
QMap< QString, CommentedElement > pendingComments
OutWriter & writeRegion(QString rName, QStringView toWrite)
void regionEnd(QString rName)
DomItem updatedFile(DomItem &qmlFile)
UpdatedScriptExpression::Tree reformattedScriptExpressions
FileLocations::Tree topLocation
void itemStart(DomItem &it)
void itemEnd(DomItem &it)
void regionStart(QString rName)
OutWriterState & state(int i=0)
Path mid(int offset, int length) const
QString toString() const
Keeps the comments associated with a DomItem.
std::shared_ptr< AttachedInfoT< UpdatedScriptExpression > > Tree
static bool visitTree(Tree base, function_ref< bool(Path, Tree)> visitor, Path basePath=Path())
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
static jboolean copy(JNIEnv *, jobject)
#define qCWarning(category,...)
GLfloat GLfloat GLfloat w
[0]
GLdouble GLdouble t
Definition qopenglext.h:243
GLfloat GLfloat p
[1]
GLuint * states
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QGraphicsItem * item