99 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- IncludeFixer.h ------------------------------------------*- C++-*-===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
 | 
						|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
 | 
						|
 | 
						|
#include "Diagnostics.h"
 | 
						|
#include "Headers.h"
 | 
						|
#include "index/Index.h"
 | 
						|
#include "index/Symbol.h"
 | 
						|
#include "clang/AST/Type.h"
 | 
						|
#include "clang/Basic/Diagnostic.h"
 | 
						|
#include "clang/Basic/SourceLocation.h"
 | 
						|
#include "clang/Sema/ExternalSemaSource.h"
 | 
						|
#include "clang/Sema/Sema.h"
 | 
						|
#include "llvm/ADT/ArrayRef.h"
 | 
						|
#include "llvm/ADT/DenseMap.h"
 | 
						|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
 | 
						|
#include "llvm/ADT/Optional.h"
 | 
						|
#include "llvm/ADT/StringMap.h"
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include <memory>
 | 
						|
 | 
						|
namespace clang {
 | 
						|
namespace clangd {
 | 
						|
 | 
						|
/// Attempts to recover from error diagnostics by suggesting include insertion
 | 
						|
/// fixes. For example, member access into incomplete type can be fixes by
 | 
						|
/// include headers with the definition.
 | 
						|
class IncludeFixer {
 | 
						|
public:
 | 
						|
  IncludeFixer(llvm::StringRef File, std::shared_ptr<IncludeInserter> Inserter,
 | 
						|
               const SymbolIndex &Index, unsigned IndexRequestLimit)
 | 
						|
      : File(File), Inserter(std::move(Inserter)), Index(Index),
 | 
						|
        IndexRequestLimit(IndexRequestLimit) {}
 | 
						|
 | 
						|
  /// Returns include insertions that can potentially recover the diagnostic.
 | 
						|
  std::vector<Fix> fix(DiagnosticsEngine::Level DiagLevel,
 | 
						|
                       const clang::Diagnostic &Info) const;
 | 
						|
 | 
						|
  /// Returns an ExternalSemaSource that records failed name lookups in Sema.
 | 
						|
  /// This allows IncludeFixer to suggest inserting headers that define those
 | 
						|
  /// names.
 | 
						|
  llvm::IntrusiveRefCntPtr<ExternalSemaSource> unresolvedNameRecorder();
 | 
						|
 | 
						|
private:
 | 
						|
  /// Attempts to recover diagnostic caused by an incomplete type \p T.
 | 
						|
  std::vector<Fix> fixIncompleteType(const Type &T) const;
 | 
						|
 | 
						|
  /// Generates header insertion fixes for all symbols. Fixes are deduplicated.
 | 
						|
  std::vector<Fix> fixesForSymbols(const SymbolSlab &Syms) const;
 | 
						|
 | 
						|
  struct UnresolvedName {
 | 
						|
    std::string Name;   // E.g. "X" in foo::X.
 | 
						|
    SourceLocation Loc; // Start location of the unresolved name.
 | 
						|
    std::vector<std::string> Scopes; // Namespace scopes we should search in.
 | 
						|
  };
 | 
						|
 | 
						|
  /// Records the last unresolved name seen by Sema.
 | 
						|
  class UnresolvedNameRecorder;
 | 
						|
 | 
						|
  /// Attempts to fix the unresolved name associated with the current
 | 
						|
  /// diagnostic. We assume a diagnostic is caused by a unresolved name when
 | 
						|
  /// they have the same source location and the unresolved name is the last
 | 
						|
  /// one we've seen during the Sema run.
 | 
						|
  std::vector<Fix> fixUnresolvedName() const;
 | 
						|
 | 
						|
  std::string File;
 | 
						|
  std::shared_ptr<IncludeInserter> Inserter;
 | 
						|
  const SymbolIndex &Index;
 | 
						|
  const unsigned IndexRequestLimit; // Make at most 5 index requests.
 | 
						|
  mutable unsigned IndexRequestCount = 0;
 | 
						|
 | 
						|
  // These collect the last unresolved name so that we can associate it with the
 | 
						|
  // diagnostic.
 | 
						|
  llvm::Optional<UnresolvedName> LastUnresolvedName;
 | 
						|
 | 
						|
  // There can be multiple diagnostics that are caused by the same unresolved
 | 
						|
  // name or incomplete type in one parse, especially when code is
 | 
						|
  // copy-and-pasted without #includes. We cache the index results based on
 | 
						|
  // index requests.
 | 
						|
  mutable llvm::StringMap<SymbolSlab> FuzzyFindCache;
 | 
						|
  mutable llvm::DenseMap<SymbolID, SymbolSlab> LookupCache;
 | 
						|
  // Returns None if the number of index requests has reached the limit.
 | 
						|
  llvm::Optional<const SymbolSlab *>
 | 
						|
  fuzzyFindCached(const FuzzyFindRequest &Req) const;
 | 
						|
  llvm::Optional<const SymbolSlab *> lookupCached(const SymbolID &ID) const;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace clangd
 | 
						|
} // namespace clang
 | 
						|
 | 
						|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
 |