//===--- Bracket.cpp - Analyze bracket structure --------------------------===// // // 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 // //===----------------------------------------------------------------------===// // // The basic phases of our bracket matching are: // // 1) A simple "greedy" match looks for well-nested subsequences. // // We can't fully trust the results of this, consider: // while (1) { // A // if (true) { // B // break; // } // C // Greedy matching will match B=C, when we should at least consider A=C. // However for the correct parts of the file, the greedy match gives the // right answer. It produces useful candidates for phase 2. // // simplePairBrackets handles this step. // // 2) Try to identify places where formatting indicates that the greedy match // was correct. This is similar to how a human would scan a large file. // // For example: // int foo() { // X // // indented // while (1) { // // valid code // } // return bar(42); // } // Y // We can "verify" that X..Y looks like a braced block, and the greedy match // tells us that substring is perfectly nested. // We trust the pairings of those brackets and don't examine them further. // However in the first example above, we do not trust B=C because the brace // indentation is suspect. // // FIXME: implement this step. // // 3) Run full best-match optimization on remaining brackets. // // Conceptually, this considers all possible matchings and optimizes cost: // - there is a cost for failing to match a bracket // - there is a variable cost for matching two brackets. // (For example if brace indentation doesn't match). // // In the first example we have three alternatives, and they are ranked: // 1) A=C, skip B // 2) B=C, skip A // 3) skip A, skip B, skip C // The cost for skipping a bracket is high, so option 3 is worst. // B=C costs more than A=C, because the indentation doesn't match. // // It would be correct to run this step alone, but it would be too slow. // The implementation is dynamic programming in N^3 space and N^2 time. // Having earlier steps filter out most brackets is key to performance. // // FIXME: implement this step. // //===----------------------------------------------------------------------===// #include "Bracket.h" namespace clang { namespace clangd { namespace { struct Bracket { … }; // Find brackets in the stream and convert to Bracket struct. std::vector<Bracket> findBrackets(const TokenStream &Stream) { … } // Write the bracket pairings from Brackets back to Tokens. void applyPairings(ArrayRef<Bracket> Brackets, TokenStream &Tokens) { … } // Find perfect pairings (ignoring whitespace) via greedy algorithm. // This means two brackets are paired if they match and the brackets between // them nest perfectly, with no skipped or crossed brackets. void simplePairBrackets(MutableArrayRef<Bracket> Brackets) { … } } // namespace void pairBrackets(TokenStream &Stream) { … } } // namespace clangd } // namespace clang