| Index: tools/gn/line_breaker.h
|
| diff --git a/tools/gn/line_breaker.h b/tools/gn/line_breaker.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f088b4ab3536b1e6f45e039d233b08d960251b59
|
| --- /dev/null
|
| +++ b/tools/gn/line_breaker.h
|
| @@ -0,0 +1,114 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef TOOLS_GN_LINE_BREAKER_H_
|
| +#define TOOLS_GN_LINE_BREAKER_H_
|
| +
|
| +#include <map>
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "tools/gn/token.h"
|
| +
|
| +class ParseNode;
|
| +
|
| +namespace commands {
|
| +
|
| +enum { kIndentSize = 2 };
|
| +enum { kMaximumWidth = 2 };
|
| +
|
| +enum Precedence {
|
| + kPrecedenceLowest,
|
| + kPrecedenceAssign,
|
| + kPrecedenceOr,
|
| + kPrecedenceAnd,
|
| + kPrecedenceCompare,
|
| + kPrecedenceAdd,
|
| + kPrecedenceSuffix,
|
| + kPrecedenceUnary,
|
| +};
|
| +
|
| +// Gives the precedence for operators in a BinaryOpNode.
|
| +Precedence GetPrecedence(const base::StringPiece op);
|
| +
|
| +class AnnotatedToken {
|
| + public:
|
| + enum Type {
|
| + UNDERLYING = Token::Type::NUM_TYPES, // Nothing additional on top of the
|
| + // basic Token::Type;
|
| + LEFT_PAREN_FUNCTION_CALL,
|
| + LEFT_PAREN_GROUPING,
|
| + LEFT_BRACKET_LIST_LITERAL,
|
| + LEFT_BRACKET_ACCESSOR,
|
| + };
|
| +
|
| + AnnotatedToken(const Token& token, Type type);
|
| + ~AnnotatedToken();
|
| +
|
| + const base::StringPiece value() const { return token_.value(); }
|
| + Type type() const {
|
| + return type_ == UNDERLYING ? static_cast<Type>(token_.type()) : type_;
|
| + }
|
| +
|
| + private:
|
| + Token token_;
|
| + Type type_;
|
| +};
|
| +
|
| +std::vector<AnnotatedToken> BuildAnnotatedTokenList(const ParseNode* statement);
|
| +
|
| +// This takes a subset of the parse tree that is considered to be one
|
| +// "statement-like" thing, as well as the column offset at which it must start.
|
| +// This might be something like an assignment 'sources = ["x"]' or the condition
|
| +// in an 'if' statement.
|
| +//
|
| +// The chunk is a flat list of tokens with extra information about what kind
|
| +// they are (for example, distinguishing between the '(' to start a function
|
| +// call, vs. a '(' in a parenthesized expression). If any line break is
|
| +// necessary to fit, try a line break between each item, summing up a penalty
|
| +// value depending on where it's broken. The set of line breaks with the lowest
|
| +// penalty score is chosen.
|
| +//
|
| +// One wrinkle is that we can't just do an exhaustive search because there are
|
| +// commonly very long statements in .gn files. For 'sources = ["0", "1", "2",
|
| +// ... "999"]' there's ~2000 possible line breaks inside the list. Checking all
|
| +// possible line breaks would be 2^2000 permutations, and ain't nobody got time
|
| +// for that. However, the penalty for ([tokenN..end] laid out at column M) is a
|
| +// cacheable value, which makes the problem tractable.
|
| +class LineBreaker {
|
| + public:
|
| + LineBreaker(const std::vector<AnnotatedToken>& annotated_tokens,
|
| + int initial_column);
|
| + ~LineBreaker();
|
| +
|
| + std::string GetBestLayout();
|
| +
|
| + private:
|
| + struct LineState {
|
| + int column;
|
| + int next;
|
| + };
|
| + void Format(int index, int start_column);
|
| +
|
| + int CalculatePenalty(LineState state, bool newline);
|
| + void AddTokenToState(bool newline, LineState* state);
|
| +
|
| + struct CacheKey {
|
| + int token_index; // The penalty is calculated from this token to the end of
|
| + // the list.
|
| + int column;
|
| + };
|
| + typedef std::map<CacheKey, int> PenaltyCache;
|
| + PenaltyCache penalty_cache_;
|
| +
|
| + const std::vector<AnnotatedToken>& annotated_tokens_;
|
| + int initial_column_;
|
| + int end_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(LineBreaker);
|
| +};
|
| +
|
| +} // namespace commands
|
| +
|
| +#endif // TOOLS_GN_LINE_BREAKER_H_
|
|
|