TextEditor: Move more code into RefactoringFile

We want to get rid of RefactoringChangesData.

Change-Id: Ia428563a0ff70ec9660761beac3eb7168b8e9eca
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2023-11-16 16:09:26 +01:00
parent 4c0abb6d2c
commit 6f3bc431fc
11 changed files with 97 additions and 127 deletions

View File

@@ -73,9 +73,7 @@
#include <QRegularExpression>
#include <cmath>
#include <new>
#include <optional>
#include <set>
#include <unordered_map>
#include <utility>
@@ -770,10 +768,9 @@ QList<Text::Range> ClangdClient::additionalDocumentHighlights(
qobject_cast<CppEditor::CppEditorWidget *>(editorWidget), cursor);
}
RefactoringChangesData *ClangdClient::createRefactoringChangesBackend() const
RefactoringFilePtr ClangdClient::createRefactoringFile(const FilePath &filePath) const
{
return new CppEditor::CppRefactoringChangesData(
CppEditor::CppModelManager::snapshot());
return CppEditor::CppRefactoringChanges(CppEditor::CppModelManager::snapshot()).file(filePath);
}
QVersionNumber ClangdClient::versionNumber() const

View File

@@ -141,7 +141,8 @@ private:
QTextCursor adjustedCursorForHighlighting(const QTextCursor &cursor,
TextEditor::TextDocument *doc) override;
const CustomInspectorTabs createCustomInspectorTabs() override;
TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const override;
TextEditor::RefactoringFilePtr createRefactoringFile(
const Utils::FilePath &filePath) const override;
LanguageClient::DiagnosticManager *createDiagnosticManager() override;
LanguageClient::LanguageClientOutlineItem *createOutlineItem(
const LanguageServerProtocol::DocumentSymbol &symbol) override;

View File

@@ -246,8 +246,9 @@ CppRefactoringChangesData *CppRefactoringFile::data() const
void CppRefactoringFile::fileChanged()
{
QTC_ASSERT(!m_filePath.isEmpty(), return);
m_cppDocument.clear();
RefactoringFile::fileChanged();
CppModelManager::updateSourceFiles({filePath()});
}
int CppRefactoringFile::tokenIndexForPosition(const std::vector<CPlusPlus::Token> &tokens,
@@ -278,35 +279,28 @@ CppRefactoringChangesData::CppRefactoringChangesData(const Snapshot &snapshot)
, m_workingCopy(CppModelManager::workingCopy())
{}
void CppRefactoringChangesData::indentSelection(const QTextCursor &selection,
const FilePath &filePath,
void CppRefactoringFile::indentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const
{
if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
textDocument->indenter()->indent(selection, QChar::Null, textDocument->tabSettings());
} else {
const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath, textDocument);
auto indenter = createIndenter(filePath, selection.document());
const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath(), textDocument);
auto indenter = createIndenter(filePath(), selection.document());
indenter->indent(selection, QChar::Null, tabSettings);
}
}
void CppRefactoringChangesData::reindentSelection(const QTextCursor &selection,
const FilePath &filePath,
void CppRefactoringFile::reindentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const
{
if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
textDocument->indenter()->reindent(selection, textDocument->tabSettings());
} else {
const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath, textDocument);
auto indenter = createIndenter(filePath, selection.document());
const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath(), textDocument);
auto indenter = createIndenter(filePath(), selection.document());
indenter->reindent(selection, tabSettings);
}
}
void CppRefactoringChangesData::fileChanged(const FilePath &filePath)
{
CppModelManager::updateSourceFiles({filePath});
}
} // CppEditor
} // namespace CppEditor

View File

@@ -51,13 +51,19 @@ public:
using TextEditor::RefactoringFile::textOf;
QString textOf(const CPlusPlus::AST *ast) const;
protected:
private:
CppRefactoringFile(const Utils::FilePath &filePath, const QSharedPointer<TextEditor::RefactoringChangesData> &data);
CppRefactoringFile(QTextDocument *document, const Utils::FilePath &filePath);
explicit CppRefactoringFile(TextEditor::TextEditorWidget *editor);
CppRefactoringChangesData *data() const;
void fileChanged() override;
void indentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const override;
virtual void reindentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const override;
int tokenIndexForPosition(const std::vector<CPlusPlus::Token> &tokens, int pos,
int startIndex) const;
@@ -72,16 +78,6 @@ class CPPEDITOR_EXPORT CppRefactoringChangesData : public TextEditor::Refactorin
public:
explicit CppRefactoringChangesData(const CPlusPlus::Snapshot &snapshot);
void indentSelection(const QTextCursor &selection,
const Utils::FilePath &filePath,
const TextEditor::TextDocument *textDocument) const override;
void reindentSelection(const QTextCursor &selection,
const Utils::FilePath &filePath,
const TextEditor::TextDocument *textDocument) const override;
void fileChanged(const Utils::FilePath &filePath) override;
CPlusPlus::Snapshot m_snapshot;
WorkingCopy m_workingCopy;
};

View File

@@ -1737,9 +1737,9 @@ void Client::log(const QString &message) const
}
}
TextEditor::RefactoringChangesData *Client::createRefactoringChangesBackend() const
TextEditor::RefactoringFilePtr Client::createRefactoringFile(const FilePath &filePath) const
{
return new TextEditor::RefactoringChangesData;
return TextEditor::RefactoringChanges().file(filePath);
}
void Client::setCompletionResultsLimit(int limit)

View File

@@ -201,7 +201,7 @@ public:
virtual const CustomInspectorTabs createCustomInspectorTabs() { return {}; }
// Caller takes ownership
virtual TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const;
virtual TextEditor::RefactoringFilePtr createRefactoringFile(const Utils::FilePath &filePath) const;
void setCompletionResultsLimit(int limit);
int completionResultsLimit() const;

View File

@@ -89,15 +89,10 @@ bool applyTextEdits(const Client *client,
{
if (edits.isEmpty())
return true;
RefactoringChangesData * const backend = client->createRefactoringChangesBackend();
RefactoringChanges changes(backend);
RefactoringFilePtr file;
file = changes.file(filePath);
const RefactoringFilePtr file = client->createRefactoringFile(filePath);
file->setChangeSet(editsToChangeSet(edits, file->document()));
if (backend) {
for (const TextEdit &edit : edits)
file->appendIndentRange(convertRange(file->document(), edit.range()));
}
return file->apply();
}

View File

@@ -24,53 +24,6 @@ public:
, m_snapshot(snapshot)
{}
void indentSelection(const QTextCursor &selection,
const Utils::FilePath &filePath,
const TextEditor::TextDocument *textDocument) const override
{
// ### shares code with QmlJSTextEditor::indent
QTextDocument *doc = selection.document();
QTextBlock block = doc->findBlock(selection.selectionStart());
const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
const TextEditor::TabSettings &tabSettings =
ProjectExplorer::actualTabSettings(filePath, textDocument);
CreatorCodeFormatter codeFormatter(tabSettings);
codeFormatter.updateStateUntil(block);
do {
int depth = codeFormatter.indentFor(block);
if (depth != -1) {
if (QStringView(block.text()).trimmed().isEmpty()) {
// we do not want to indent empty lines (as one is indentent when pressing tab
// assuming that the user will start writing something), and get rid of that
// space if one had pressed tab in an empty line just before refactoring.
// If depth == -1 (inside a multiline string for example) leave the spaces.
depth = 0;
}
tabSettings.indentLine(block, depth);
}
codeFormatter.updateLineStateChange(block);
block = block.next();
} while (block.isValid() && block != end);
}
void reindentSelection(const QTextCursor &selection,
const Utils::FilePath &filePath,
const TextEditor::TextDocument *textDocument) const override
{
const TextEditor::TabSettings &tabSettings =
ProjectExplorer::actualTabSettings(filePath, textDocument);
QmlJSEditor::Internal::Indenter indenter(selection.document());
indenter.reindent(selection, tabSettings);
}
void fileChanged(const Utils::FilePath &filePath) override
{
m_modelManager->updateSourceFiles({filePath}, true);
}
ModelManagerInterface *m_modelManager;
Snapshot m_snapshot;
};
@@ -193,8 +146,49 @@ QmlJSRefactoringChangesData *QmlJSRefactoringFile::data() const
void QmlJSRefactoringFile::fileChanged()
{
QTC_ASSERT(!m_filePath.isEmpty(), return);
m_qmljsDocument.clear();
RefactoringFile::fileChanged();
data()->m_modelManager->updateSourceFiles({filePath()}, true);
}
void QmlJSRefactoringFile::indentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const
{
// ### shares code with QmlJSTextEditor::indent
QTextDocument *doc = selection.document();
QTextBlock block = doc->findBlock(selection.selectionStart());
const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
const TextEditor::TabSettings &tabSettings =
ProjectExplorer::actualTabSettings(filePath(), textDocument);
CreatorCodeFormatter codeFormatter(tabSettings);
codeFormatter.updateStateUntil(block);
do {
int depth = codeFormatter.indentFor(block);
if (depth != -1) {
if (QStringView(block.text()).trimmed().isEmpty()) {
// we do not want to indent empty lines (as one is indentent when pressing tab
// assuming that the user will start writing something), and get rid of that
// space if one had pressed tab in an empty line just before refactoring.
// If depth == -1 (inside a multiline string for example) leave the spaces.
depth = 0;
}
tabSettings.indentLine(block, depth);
}
codeFormatter.updateLineStateChange(block);
block = block.next();
} while (block.isValid() && block != end);
}
void QmlJSRefactoringFile::reindentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const
{
const TextEditor::TabSettings &tabSettings =
ProjectExplorer::actualTabSettings(filePath(), textDocument);
QmlJSEditor::Internal::Indenter indenter(selection.document());
indenter.reindent(selection, tabSettings);
}
} // namespace QmlJSTools

View File

@@ -34,13 +34,18 @@ public:
bool isCursorOn(QmlJS::AST::UiQualifiedId *ast) const;
bool isCursorOn(QmlJS::SourceLocation loc) const;
protected:
private:
QmlJSRefactoringFile(const Utils::FilePath &filePath,
const QSharedPointer<TextEditor::RefactoringChangesData> &data);
QmlJSRefactoringFile(TextEditor::TextEditorWidget *editor, QmlJS::Document::Ptr document);
QmlJSRefactoringChangesData *data() const;
void fileChanged() override;
void indentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const override;
void reindentSelection(const QTextCursor &selection,
const TextEditor::TextDocument *textDocument) const override;
mutable QmlJS::Document::Ptr m_qmljsDocument;

View File

@@ -118,7 +118,7 @@ bool RefactoringFile::create(const QString &contents, bool reindent, bool openEd
// Reindent the contents:
if (reindent) {
cursor.select(QTextCursor::Document);
m_data->indentSelection(cursor, m_filePath, nullptr);
indentSelection(cursor, nullptr);
}
cursor.endEditBlock();
@@ -375,9 +375,9 @@ void RefactoringFile::indentOrReindent(const RefactoringSelections &ranges,
QTextCursor selection(anchor);
selection.setPosition(position.position(), QTextCursor::KeepAnchor);
if (indent == Indent)
m_data->indentSelection(selection, m_filePath, document);
indentSelection(selection, document);
else
m_data->reindentSelection(selection, m_filePath, document);
reindentSelection(selection, document);
}
}
@@ -479,30 +479,20 @@ void RefactoringFile::doFormatting()
}
}
void RefactoringFile::fileChanged()
void RefactoringFile::indentSelection(const QTextCursor &selection,
const TextDocument *textDocument) const
{
if (!m_filePath.isEmpty())
m_data->fileChanged(m_filePath);
Q_UNUSED(selection)
Q_UNUSED(textDocument)
}
void RefactoringFile::reindentSelection(const QTextCursor &selection,
const TextDocument *textDocument) const
{
Q_UNUSED(selection)
Q_UNUSED(textDocument)
}
RefactoringChangesData::~RefactoringChangesData() = default;
void RefactoringChangesData::indentSelection(const QTextCursor &,
const FilePath &,
const TextDocument *) const
{
qWarning() << Q_FUNC_INFO << "not implemented";
}
void RefactoringChangesData::reindentSelection(const QTextCursor &,
const FilePath &,
const TextDocument *) const
{
qWarning() << Q_FUNC_INFO << "not implemented";
}
void RefactoringChangesData::fileChanged(const FilePath &)
{
}
} // namespace TextEditor

View File

@@ -72,8 +72,9 @@ protected:
const QSharedPointer<RefactoringChangesData> &data);
QTextDocument *mutableDocument() const;
// derived classes may want to clear language specific extra data
virtual void fileChanged();
virtual void fileChanged() {}
enum IndentType {Indent, Reindent};
void indentOrReindent(const RefactoringSelections &ranges, IndentType indent);
@@ -81,6 +82,11 @@ protected:
void setupFormattingRanges(const QList<Utils::ChangeSet::EditOp> &replaceList);
void doFormatting();
virtual void indentSelection(const QTextCursor &selection,
const TextDocument *textDocument) const;
virtual void reindentSelection(const QTextCursor &selection,
const TextDocument *textDocument) const;
Utils::FilePath m_filePath;
QSharedPointer<RefactoringChangesData> m_data;
mutable Utils::TextFileFormat m_textFileFormat;
@@ -140,14 +146,6 @@ class TEXTEDITOR_EXPORT RefactoringChangesData
public:
RefactoringChangesData() = default;
virtual ~RefactoringChangesData();
virtual void indentSelection(const QTextCursor &selection,
const Utils::FilePath &filePath,
const TextDocument *textEditor) const;
virtual void reindentSelection(const QTextCursor &selection,
const Utils::FilePath &filePath,
const TextDocument *textEditor) const;
virtual void fileChanged(const Utils::FilePath &filePath);
};
} // namespace TextEditor