c.s.tools.ide.analysis.modernize/src/com/sun/tools/ide/analysis/modernize/tools-clang.patch
author Ilia Gromov <ilia@netbeans.org>
Wed, 07 Jun 2017 20:23:29 +0300
branchrelease82
changeset 18423 b9d9af239a0c
permissions -rw-r--r--
Fixing #270763 - Move clang-tidy integration to nb contrib
* * *
Fixing #270763 - Move clang-tidy integration to nb contrib - move wrapper
* * *
Fixing #270763 - Move clang-tidy integration to nb contrib - sign nbm
* * *
Fixing #270763 - Move clang-tidy integration to nb contrib - move tests
* * *
Fixing #270763 - Move clang-tidy integration to nb contrib - data for a new test
* * *
Fixed #270839 - [clang-tidy] Group checks in Editor hints
(transplanted from 35b6125ef00c470655dac6673075f5c12ec74593)
     1 Index: include/clang/Tooling/Core/Diagnostics.h
     2 ===================================================================
     3 --- include/clang/Tooling/Core/Diagnostics.h	(revision 278390)
     4 +++ include/clang/Tooling/Core/Diagnostics.h	(working copy)
     5 @@ -1,254 +1,54 @@
     6 -//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===//
     7 -//
     8 -//                     The LLVM Compiler Infrastructure
     9 -//
    10 -// This file is distributed under the University of Illinois Open Source
    11 -// License. See LICENSE.TXT for details.
    12 -//
    13 -//===----------------------------------------------------------------------===//
    14 -//
    15 -//  Classes supporting refactorings that span multiple translation units.
    16 -//  While single translation unit refactorings are supported via the Rewriter,
    17 -//  when refactoring multiple translation units changes must be stored in a
    18 -//  SourceManager independent form, duplicate changes need to be removed, and
    19 -//  all changes must be applied at once at the end of the refactoring so that
    20 -//  the code is always parseable.
    21 -//
    22 -//===----------------------------------------------------------------------===//
    23 -
    24 -#ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
    25 -#define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
    26 -
    27 -#include "clang/Basic/LangOptions.h"
    28 -#include "clang/Basic/SourceLocation.h"
    29 -#include "llvm/ADT/StringRef.h"
    30 -#include "llvm/Support/Error.h"
    31 -#include <map>
    32 -#include <set>
    33 +#ifndef LLVM_CLANG_TOOLING_CORE_DIAGNOSTICS_H
    34 +#define LLVM_CLANG_TOOLING_CORE_DIAGNOSTICS_H
    35 +#include "clang/Basic/Diagnostic.h"
    36 +#include "llvm/ADT/SmallVector.h"
    37 +#include "Replacement.h"
    38  #include <string>
    39 -#include <vector>
    40 -
    41  namespace clang {
    42 +    namespace tooling {
    43  
    44 -class Rewriter;
    45 +        struct DiagnosticsMessage {
    46 +            DiagnosticsMessage(StringRef Message = "");
    47 +            DiagnosticsMessage(StringRef Message, const SourceManager &Sources,
    48 +                    SourceLocation Loc);
    49 +            std::string Message;
    50 +            std::string FilePath;
    51 +            unsigned FileOffset;
    52 +        };
    53  
    54 -namespace tooling {
    55 +        struct Diagnostics {
    56  
    57 -/// \brief A source range independent of the \c SourceManager.
    58 -class Range {
    59 -public:
    60 -  Range() : Offset(0), Length(0) {}
    61 -  Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
    62 +            enum Level {
    63 +                Warning = DiagnosticsEngine::Warning,
    64 +                Error = DiagnosticsEngine::Error
    65 +            };
    66  
    67 -  /// \brief Accessors.
    68 -  /// @{
    69 -  unsigned getOffset() const { return Offset; }
    70 -  unsigned getLength() const { return Length; }
    71 -  /// @}
    72 +            Diagnostics();
    73 +            Diagnostics(StringRef CheckName, Level DiagLevel, bool IsWarningAsError,
    74 +                    StringRef BuildDirectory);
    75 +            std::string CheckName;
    76 +            DiagnosticsMessage Message;
    77 +            tooling::Replacements Fix;
    78 +            SmallVector<DiagnosticsMessage, 1> Notes;
    79  
    80 -  /// \name Range Predicates
    81 -  /// @{
    82 -  /// \brief Whether this range overlaps with \p RHS or not.
    83 -  bool overlapsWith(Range RHS) const {
    84 -    return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
    85 -  }
    86 +            // A build directory of the diagnostic source file.
    87 +            //
    88 +            // It's an absolute path which is `directory` field of the source file in
    89 +            // compilation database. If users don't specify the compilation database
    90 +            // directory, it is the current directory where clang-tidy runs.
    91 +            //
    92 +            // Note: it is empty in unittest.
    93 +            std::string BuildDirectory;
    94  
    95 -  /// \brief Whether this range contains \p RHS or not.
    96 -  bool contains(Range RHS) const {
    97 -    return RHS.Offset >= Offset &&
    98 -           (RHS.Offset + RHS.Length) <= (Offset + Length);
    99 -  }
   100 +            Level DiagLevel;
   101 +            bool IsWarningAsError;
   102 +        };
   103  
   104 -  /// \brief Whether this range equals to \p RHS or not.
   105 -  bool operator==(const Range &RHS) const {
   106 -    return Offset == RHS.getOffset() && Length == RHS.getLength();
   107 -  }
   108 -  /// @}
   109 -
   110 -private:
   111 -  unsigned Offset;
   112 -  unsigned Length;
   113 -};
   114 -
   115 -/// \brief A text replacement.
   116 -///
   117 -/// Represents a SourceManager independent replacement of a range of text in a
   118 -/// specific file.
   119 -class Replacement {
   120 -public:
   121 -  /// \brief Creates an invalid (not applicable) replacement.
   122 -  Replacement();
   123 -
   124 -  /// \brief Creates a replacement of the range [Offset, Offset+Length) in
   125 -  /// FilePath with ReplacementText.
   126 -  ///
   127 -  /// \param FilePath A source file accessible via a SourceManager.
   128 -  /// \param Offset The byte offset of the start of the range in the file.
   129 -  /// \param Length The length of the range in bytes.
   130 -  Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
   131 -              StringRef ReplacementText);
   132 -
   133 -  /// \brief Creates a Replacement of the range [Start, Start+Length) with
   134 -  /// ReplacementText.
   135 -  Replacement(const SourceManager &Sources, SourceLocation Start,
   136 -              unsigned Length, StringRef ReplacementText);
   137 -
   138 -  /// \brief Creates a Replacement of the given range with ReplacementText.
   139 -  Replacement(const SourceManager &Sources, const CharSourceRange &Range,
   140 -              StringRef ReplacementText,
   141 -              const LangOptions &LangOpts = LangOptions());
   142 -
   143 -  /// \brief Creates a Replacement of the node with ReplacementText.
   144 -  template <typename Node>
   145 -  Replacement(const SourceManager &Sources, const Node &NodeToReplace,
   146 -              StringRef ReplacementText,
   147 -              const LangOptions &LangOpts = LangOptions());
   148 -
   149 -  /// \brief Returns whether this replacement can be applied to a file.
   150 -  ///
   151 -  /// Only replacements that are in a valid file can be applied.
   152 -  bool isApplicable() const;
   153 -
   154 -  /// \brief Accessors.
   155 -  /// @{
   156 -  StringRef getFilePath() const { return FilePath; }
   157 -  unsigned getOffset() const { return ReplacementRange.getOffset(); }
   158 -  unsigned getLength() const { return ReplacementRange.getLength(); }
   159 -  StringRef getReplacementText() const { return ReplacementText; }
   160 -  /// @}
   161 -
   162 -  /// \brief Applies the replacement on the Rewriter.
   163 -  bool apply(Rewriter &Rewrite) const;
   164 -
   165 -  /// \brief Returns a human readable string representation.
   166 -  std::string toString() const;
   167 -
   168 - private:
   169 -   void setFromSourceLocation(const SourceManager &Sources,
   170 -                              SourceLocation Start, unsigned Length,
   171 -                              StringRef ReplacementText);
   172 -   void setFromSourceRange(const SourceManager &Sources,
   173 -                           const CharSourceRange &Range,
   174 -                           StringRef ReplacementText,
   175 -                           const LangOptions &LangOpts);
   176 -
   177 -  std::string FilePath;
   178 -  Range ReplacementRange;
   179 -  std::string ReplacementText;
   180 -};
   181 -
   182 -/// \brief Less-than operator between two Replacements.
   183 -bool operator<(const Replacement &LHS, const Replacement &RHS);
   184 -
   185 -/// \brief Equal-to operator between two Replacements.
   186 -bool operator==(const Replacement &LHS, const Replacement &RHS);
   187 -
   188 -/// \brief A set of Replacements.
   189 -/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
   190 -typedef std::set<Replacement> Replacements;
   191 -
   192 -/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
   193 -///
   194 -/// Replacement applications happen independently of the success of
   195 -/// other applications.
   196 -///
   197 -/// \returns true if all replacements apply. false otherwise.
   198 -bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
   199 -
   200 -/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
   201 -///
   202 -/// Replacement applications happen independently of the success of
   203 -/// other applications.
   204 -///
   205 -/// \returns true if all replacements apply. false otherwise.
   206 -bool applyAllReplacements(const std::vector<Replacement> &Replaces,
   207 -                          Rewriter &Rewrite);
   208 -
   209 -/// \brief Applies all replacements in \p Replaces to \p Code.
   210 -///
   211 -/// This completely ignores the path stored in each replacement. If all
   212 -/// replacements are applied successfully, this returns the code with
   213 -/// replacements applied; otherwise, an llvm::Error carrying llvm::StringError
   214 -/// is returned (the Error message can be converted to string using
   215 -/// `llvm::toString()` and 'std::error_code` in the `Error` should be ignored).
   216 -llvm::Expected<std::string> applyAllReplacements(StringRef Code,
   217 -                                                 const Replacements &Replaces);
   218 -
   219 -/// \brief Calculates how a code \p Position is shifted when \p Replaces are
   220 -/// applied.
   221 -unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
   222 -
   223 -/// \brief Calculates how a code \p Position is shifted when \p Replaces are
   224 -/// applied.
   225 -///
   226 -/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
   227 -unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
   228 -                             unsigned Position);
   229 -
   230 -/// \brief Removes duplicate Replacements and reports if Replacements conflict
   231 -/// with one another. All Replacements are assumed to be in the same file.
   232 -///
   233 -/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
   234 -///
   235 -/// This function sorts \p Replaces so that conflicts can be reported simply by
   236 -/// offset into \p Replaces and number of elements in the conflict.
   237 -void deduplicate(std::vector<Replacement> &Replaces,
   238 -                 std::vector<Range> &Conflicts);
   239 -
   240 -/// \brief Collection of Replacements generated from a single translation unit.
   241 -struct TranslationUnitReplacements {
   242 -  /// Name of the main source for the translation unit.
   243 -  std::string MainSourceFile;
   244 -
   245 -  /// A freeform chunk of text to describe the context of the replacements.
   246 -  /// Will be printed, for example, when detecting conflicts during replacement
   247 -  /// deduplication.
   248 -  std::string Context;
   249 -
   250 -  std::vector<Replacement> Replacements;
   251 -};
   252 -
   253 -/// \brief Calculates the ranges in a single file that are affected by the
   254 -/// Replacements. Overlapping ranges will be merged.
   255 -///
   256 -/// \pre Replacements must be for the same file.
   257 -///
   258 -/// \returns a non-overlapping and sorted ranges.
   259 -std::vector<Range> calculateChangedRanges(const Replacements &Replaces);
   260 -
   261 -/// \brief Calculates the new ranges after \p Replaces are applied. These
   262 -/// include both the original \p Ranges and the affected ranges of \p Replaces
   263 -/// in the new code.
   264 -///
   265 -/// \pre Replacements must be for the same file.
   266 -///
   267 -/// \return The new ranges after \p Replaces are applied. The new ranges will be
   268 -/// sorted and non-overlapping.
   269 -std::vector<Range>
   270 -calculateRangesAfterReplacements(const Replacements &Replaces,
   271 -                                 const std::vector<Range> &Ranges);
   272 -
   273 -/// \brief Groups a random set of replacements by file path. Replacements
   274 -/// related to the same file entry are put into the same vector.
   275 -std::map<std::string, Replacements>
   276 -groupReplacementsByFile(const Replacements &Replaces);
   277 -
   278 -/// \brief Merges two sets of replacements with the second set referring to the
   279 -/// code after applying the first set. Within both 'First' and 'Second',
   280 -/// replacements must not overlap.
   281 -Replacements mergeReplacements(const Replacements &First,
   282 -                               const Replacements &Second);
   283 -
   284 -template <typename Node>
   285 -Replacement::Replacement(const SourceManager &Sources,
   286 -                         const Node &NodeToReplace, StringRef ReplacementText,
   287 -                         const LangOptions &LangOpts) {
   288 -  const CharSourceRange Range =
   289 -      CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
   290 -  setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
   291 +        struct TranslationUnitDiagnostics {
   292 +            std::string MainSourceFile;
   293 +            std::string Context;
   294 +            std::vector<Diagnostics> Diags;
   295 +        };
   296 +    }
   297  }
   298 -
   299 -} // end namespace tooling
   300 -} // end namespace clang
   301 -
   302 -#endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
   303 +#endif
   304 \ No newline at end of file
   305 Index: lib/Tooling/Core/CMakeLists.txt
   306 ===================================================================
   307 --- lib/Tooling/Core/CMakeLists.txt	(revision 278390)
   308 +++ lib/Tooling/Core/CMakeLists.txt	(working copy)
   309 @@ -3,6 +3,7 @@
   310  add_clang_library(clangToolingCore
   311    Lookup.cpp
   312    Replacement.cpp
   313 +  Diagnostics.cpp
   314    QualTypeNames.cpp
   315  
   316    LINK_LIBS
   317 Index: lib/Tooling/Core/Diagnostics.cpp
   318 ===================================================================
   319 --- lib/Tooling/Core/Diagnostics.cpp	(revision 278390)
   320 +++ lib/Tooling/Core/Diagnostics.cpp	(working copy)
   321 @@ -1,113 +1,30 @@
   322 -//===--- Lookup.cpp - Framework for clang refactoring tools ---------------===//
   323 -//
   324 -//                     The LLVM Compiler Infrastructure
   325 -//
   326 -// This file is distributed under the University of Illinois Open Source
   327 -// License. See LICENSE.TXT for details.
   328 -//
   329 -//===----------------------------------------------------------------------===//
   330 -//
   331 -//  This file defines helper methods for clang tools performing name lookup.
   332 -//
   333 -//===----------------------------------------------------------------------===//
   334 +#include "clang/Tooling/Core/Diagnostics.h"
   335 +#include "clang/Basic/SourceManager.h"
   336 +namespace clang {
   337 +    namespace tooling {
   338  
   339 -#include "clang/Tooling/Core/Lookup.h"
   340 -#include "clang/AST/Decl.h"
   341 -using namespace clang;
   342 -using namespace clang::tooling;
   343 +        DiagnosticsMessage::DiagnosticsMessage(StringRef Message)
   344 +        : Message(Message), FileOffset(0) {
   345 +        }
   346  
   347 -static bool isInsideDifferentNamespaceWithSameName(const DeclContext *DeclA,
   348 -                                                   const DeclContext *DeclB) {
   349 -  while (true) {
   350 -    // Look past non-namespaces on DeclA.
   351 -    while (DeclA && !isa<NamespaceDecl>(DeclA))
   352 -      DeclA = DeclA->getParent();
   353 +        DiagnosticsMessage::DiagnosticsMessage(StringRef Message,
   354 +                const SourceManager &Sources,
   355 +                SourceLocation Loc)
   356 +        : Message(Message) {
   357 +            assert(Loc.isValid() && Loc.isFileID());
   358 +            FilePath = Sources.getFilename(Loc);
   359 +            FileOffset = Sources.getFileOffset(Loc);
   360 +        }
   361  
   362 -    // Look past non-namespaces on DeclB.
   363 -    while (DeclB && !isa<NamespaceDecl>(DeclB))
   364 -      DeclB = DeclB->getParent();
   365 +        Diagnostics::Diagnostics() {
   366 +        }
   367  
   368 -    // We hit the root, no namespace collision.
   369 -    if (!DeclA || !DeclB)
   370 -      return false;
   371 -
   372 -    // Literally the same namespace, not a collision.
   373 -    if (DeclA == DeclB)
   374 -      return false;
   375 -
   376 -    // Now check the names. If they match we have a different namespace with the
   377 -    // same name.
   378 -    if (cast<NamespaceDecl>(DeclA)->getDeclName() ==
   379 -        cast<NamespaceDecl>(DeclB)->getDeclName())
   380 -      return true;
   381 -
   382 -    DeclA = DeclA->getParent();
   383 -    DeclB = DeclB->getParent();
   384 -  }
   385 -}
   386 -
   387 -static StringRef getBestNamespaceSubstr(const DeclContext *DeclA,
   388 -                                        StringRef NewName,
   389 -                                        bool HadLeadingColonColon) {
   390 -  while (true) {
   391 -    while (DeclA && !isa<NamespaceDecl>(DeclA))
   392 -      DeclA = DeclA->getParent();
   393 -
   394 -    // Fully qualified it is! Leave :: in place if it's there already.
   395 -    if (!DeclA)
   396 -      return HadLeadingColonColon ? NewName : NewName.substr(2);
   397 -
   398 -    // Otherwise strip off redundant namespace qualifications from the new name.
   399 -    // We use the fully qualified name of the namespace and remove that part
   400 -    // from NewName if it has an identical prefix.
   401 -    std::string NS =
   402 -        "::" + cast<NamespaceDecl>(DeclA)->getQualifiedNameAsString() + "::";
   403 -    if (NewName.startswith(NS))
   404 -      return NewName.substr(NS.size());
   405 -
   406 -    // No match yet. Strip of a namespace from the end of the chain and try
   407 -    // again. This allows to get optimal qualifications even if the old and new
   408 -    // decl only share common namespaces at a higher level.
   409 -    DeclA = DeclA->getParent();
   410 -  }
   411 -}
   412 -
   413 -/// Check if the name specifier begins with a written "::".
   414 -static bool isFullyQualified(const NestedNameSpecifier *NNS) {
   415 -  while (NNS) {
   416 -    if (NNS->getKind() == NestedNameSpecifier::Global)
   417 -      return true;
   418 -    NNS = NNS->getPrefix();
   419 -  }
   420 -  return false;
   421 -}
   422 -
   423 -std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
   424 -                                       const DeclContext *UseContext,
   425 -                                       const NamedDecl *FromDecl,
   426 -                                       StringRef ReplacementString) {
   427 -  assert(ReplacementString.startswith("::") &&
   428 -         "Expected fully-qualified name!");
   429 -
   430 -  // We can do a raw name replacement when we are not inside the namespace for
   431 -  // the original function and it is not in the global namespace.  The
   432 -  // assumption is that outside the original namespace we must have a using
   433 -  // statement that makes this work out and that other parts of this refactor
   434 -  // will automatically fix using statements to point to the new function
   435 -  const bool class_name_only = !Use;
   436 -  const bool in_global_namespace =
   437 -      isa<TranslationUnitDecl>(FromDecl->getDeclContext());
   438 -  if (class_name_only && !in_global_namespace &&
   439 -      !isInsideDifferentNamespaceWithSameName(FromDecl->getDeclContext(),
   440 -                                              UseContext)) {
   441 -    auto Pos = ReplacementString.rfind("::");
   442 -    return Pos != StringRef::npos ? ReplacementString.substr(Pos + 2)
   443 -                                  : ReplacementString;
   444 -  }
   445 -  // We did not match this because of a using statement, so we will need to
   446 -  // figure out how good a namespace match we have with our destination type.
   447 -  // We work backwards (from most specific possible namespace to least
   448 -  // specific).
   449 -  return getBestNamespaceSubstr(UseContext, ReplacementString,
   450 -                                isFullyQualified(Use));
   451 -}
   452 +        Diagnostics::Diagnostics(StringRef CheckName,
   453 +                Diagnostics::Level DiagLevel,
   454 +                bool IsWarningAsError,
   455 +                StringRef BuildDirectory)
   456 +        : CheckName(CheckName), BuildDirectory(BuildDirectory), DiagLevel(DiagLevel),
   457 +        IsWarningAsError(IsWarningAsError) {
   458 +        }
   459 +    }
   460 +}
   461 \ No newline at end of file