/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include "config_clang.h" #include "compat.hxx" #include "plugin.hxx" /** Look for comparisons where the constant is on the left, it should be on the right. */ namespace { class ComparisonWithConstant : public loplugin::FilteringRewritePlugin { public: explicit ComparisonWithConstant(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) {} virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } // Deliberately drop RecursiveASTVisitor::TraverseBinaryOperator's DataRecursionQueue // parameter; TraverseBinaryOperator must use stack instead of data recursion for any // children's VisitBinaryOperator to see changes to occurrence_ by a parent // VisitBinaryOperator: bool TraverseBinaryOperator(BinaryOperator * S) { auto const op = S->getOpcode(); if (op != BO_EQ && op != BO_NE) { return RecursiveASTVisitor::TraverseBinaryOperator(S); } auto const saved = occurrence_; auto const ret = RecursiveASTVisitor::TraverseBinaryOperator(S); occurrence_ = saved; return ret; } #if CLANG_VERSION < 110000 bool TraverseBinEQ(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } bool TraverseBinNE(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } #endif bool VisitBinaryOperator(const BinaryOperator *); private: bool rewrite(const BinaryOperator *); std::string getExprAsString(SourceRange range); SourceRange ignoreMacroExpansions(SourceRange range); bool occurrence_ = false; }; bool ComparisonWithConstant::VisitBinaryOperator(const BinaryOperator* binaryOp) { if (ignoreLocation(binaryOp)) { return true; } if (!(binaryOp->getOpcode() == BO_EQ || binaryOp->getOpcode() == BO_NE)) { return true; } // protect against clang assert if (binaryOp->getLHS()->isValueDependent() || binaryOp->getRHS()->isValueDependent()) { return true; } if (!binaryOp->getLHS()->isEvaluatable(compiler.getASTContext())) { return true; } if (binaryOp->getRHS()->isEvaluatable(compiler.getASTContext())) { return true; } if (occurrence_ || !rewrite(binaryOp)) { report( DiagnosticsEngine::Warning, "Rather put constant on right when comparing", binaryOp->getSourceRange().getBegin()) << binaryOp->getSourceRange(); } occurrence_ = true; return true; } bool ComparisonWithConstant::rewrite(const BinaryOperator * binaryOp) { if (rewriter == nullptr) { return false; } auto lhsRange = ignoreMacroExpansions(binaryOp->getLHS()->getSourceRange()); if (!lhsRange.isValid()) { return false; } auto rhsRange = ignoreMacroExpansions(binaryOp->getRHS()->getSourceRange()); if (!rhsRange.isValid()) { return false; } const std::string lhsString = getExprAsString(lhsRange); const std::string rhsString = getExprAsString(rhsRange); // switch LHS and RHS if (!replaceText(lhsRange, rhsString)) { return false; } if (!replaceText(rhsRange, lhsString)) { return false; } return true; } // get the expression contents std::string ComparisonWithConstant::getExprAsString(SourceRange range) { SourceManager& SM = compiler.getSourceManager(); SourceLocation startLoc = range.getBegin(); SourceLocation endLoc = range.getEnd(); const char *p1 = SM.getCharacterData( startLoc ); const char *p2 = SM.getCharacterData( endLoc ); unsigned n = Lexer::MeasureTokenLength( endLoc, SM, compiler.getLangOpts()); return std::string( p1, p2 - p1 + n); } SourceRange ComparisonWithConstant::ignoreMacroExpansions(SourceRange range) { while (compiler.getSourceManager().isMacroArgExpansion(range.getBegin())) { range.setBegin( compiler.getSourceManager().getImmediateMacroCallerLoc( range.getBegin())); } if (range.getBegin().isMacroID()) { SourceLocation loc; if (Lexer::isAtStartOfMacroExpansion( range.getBegin(), compiler.getSourceManager(), compiler.getLangOpts(), &loc)) { range.setBegin(loc); } } while (compiler.getSourceManager().isMacroArgExpansion(range.getEnd())) { range.setEnd( compiler.getSourceManager().getImmediateMacroCallerLoc( range.getEnd())); } if (range.getEnd().isMacroID()) { SourceLocation loc; if (Lexer::isAtEndOfMacroExpansion( range.getEnd(), compiler.getSourceManager(), compiler.getLangOpts(), &loc)) { range.setEnd(loc); } } return range.getBegin().isMacroID() || range.getEnd().isMacroID() ? SourceRange() : range; } loplugin::Plugin::Registration< ComparisonWithConstant > X("comparisonwithconstant", false); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ ackports'>distro/lhm/libreoffice-5-2+backports LibreOffice 核心代码仓库文档基金会
summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2021-05-10rename to remove the gtk3 prefixCaolán McNamara
Change-Id: I219798ed42aff11d09fd45c26ca1a018c2d22c08 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115239 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2018-01-23Introduce gtk3_kde5 vcl pluginMilian Wolff
This is a hybrid plugin which mostly wraps the GTK3 vclplug. Only the file and folder picker are replaced by KDE dialogs. This gives us a well-maintained GTK LO base with basic KDE integration with minimum effort. To prevent issues with nested event loops, the KDE dialogs are launched from a separate process, the new lo_kde5filepicker helper executable. A trivial stdin/stdout IPC mechanism transfers the data between LO and the Qt/KDE helper. The usage of an external process also allows us to copy'n'paste between LO and the KDE file dialog without freezing the UI, as would happen when one would do this in-process. This is in general also the architecture applied by the kmozillahelper, which is used to integrate KDE file dialogs into Firefox. While the KDE dialog is shown, the GTK3 main window is disabled and close requests are ignored. The KDE dialog in turn also sets the LO window as transient parent. Together, this makes the illusion perfect and the KDE dialog behaves like a modal dialog. This works properly also with multiple LO main windows, and only individual windows will get blocked as one would expect. Functionality wise, most of the features of the KDE4 dialog are supported. You can pick files and folders, and save files under a new name. Some custom checkbox widgets are supported, but lists, buttons and preview widgets are not yet implemented. Also, loading remote files via KIO is not possible yet. Change-Id: I1a97cf7c272307a19ace4222d5f12253bc722829 Reviewed-on: https://gerrit.libreoffice.org/47718 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>