|  | // Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  | package com.android.tools.r8; | 
|  |  | 
|  | import com.android.tools.r8.utils.StringUtils; | 
|  | import java.util.ArrayList; | 
|  | import java.util.List; | 
|  |  | 
|  | /** | 
|  | * Public utility for printing R8/D8 command line flags. | 
|  | * | 
|  | * <p>This utility can be used to support wrapping the compilers command-line interface. | 
|  | */ | 
|  | @Keep | 
|  | public class ParseFlagPrinter { | 
|  |  | 
|  | private final List<ParseFlagInfo> flags = new ArrayList<>(); | 
|  |  | 
|  | private String prefix = "  "; | 
|  | private int helpColumn = 25; | 
|  | private String helpSeparator = " # "; | 
|  |  | 
|  | // Formatting state. | 
|  | private StringBuilder builder = null; | 
|  | private int currentColumn = -1; | 
|  |  | 
|  | // We use -1 to denote the unstarted line, otherwise we can't distinguish it when prefix is empty. | 
|  | private boolean isLineStarted() { | 
|  | return currentColumn >= 0; | 
|  | } | 
|  |  | 
|  | private void append(String string) { | 
|  | assert isLineStarted(); | 
|  | builder.append(string); | 
|  | currentColumn += string.length(); | 
|  | } | 
|  |  | 
|  | private void space(int space) { | 
|  | assert isLineStarted(); | 
|  | for (int i = 0; i < space; i++) { | 
|  | builder.append(' '); | 
|  | } | 
|  | currentColumn += space; | 
|  | } | 
|  |  | 
|  | private void endLine() { | 
|  | assert isLineStarted(); | 
|  | builder.append(StringUtils.LINE_SEPARATOR); | 
|  | currentColumn = -1; | 
|  | } | 
|  |  | 
|  | private void startLine() { | 
|  | assert !isLineStarted(); | 
|  | currentColumn = 0; | 
|  | append(prefix); | 
|  | } | 
|  |  | 
|  | private void addFlagLine(String flagLine) { | 
|  | if (isLineStarted()) { | 
|  | endLine(); | 
|  | } | 
|  | startLine(); | 
|  | append(flagLine); | 
|  | } | 
|  |  | 
|  | private void addHelpLine(String helpLine) { | 
|  | // If the current line is already past the point for printing help implicitly end the line. | 
|  | if (currentColumn > helpColumn) { | 
|  | endLine(); | 
|  | } | 
|  | if (!isLineStarted()) { | 
|  | startLine(); | 
|  | } | 
|  | int distanceToHelpColum = helpColumn - currentColumn; | 
|  | space(distanceToHelpColum); | 
|  | append(helpSeparator); | 
|  | append(helpLine); | 
|  | endLine(); | 
|  | } | 
|  |  | 
|  | private void formatParseFlags() { | 
|  | for (ParseFlagInfo flag : flags) { | 
|  | addFlagLine(flag.getFlagFormat()); | 
|  | flag.getFlagFormatAlternatives().forEach(this::addFlagLine); | 
|  | flag.getFlagHelp().forEach(this::addHelpLine); | 
|  | } | 
|  | } | 
|  |  | 
|  | public ParseFlagPrinter addFlags(List<ParseFlagInfo> flags) { | 
|  | this.flags.addAll(flags); | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** Set a prefix which will be prepended to each line (flags and help lines). */ | 
|  | public ParseFlagPrinter setPrefix(String prefix) { | 
|  | this.prefix = prefix; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** Convenience method to set the prefix to be 'indent' number of spaces. */ | 
|  | public ParseFlagPrinter setIndent(int indent) { | 
|  | return setPrefix(" ".repeat(indent)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set the column at which the help information should start. | 
|  | * | 
|  | * <p>If a flag header extends past the end of the help column, then the help will start on a new | 
|  | * line at the point of the specified help column. | 
|  | */ | 
|  | public ParseFlagPrinter setHelpColumn(int helpColumn) { | 
|  | this.helpColumn = helpColumn; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set the separator to use to split the help information from the flag info. | 
|  | * | 
|  | * <p>This is prefixed to every help line and thus extends the size of each help line. The help | 
|  | * separator will always start at exactly the help column ({@see setHelpColumn(int)}. | 
|  | */ | 
|  | public ParseFlagPrinter setHelpSeparator(String helpSeparator) { | 
|  | this.helpSeparator = helpSeparator; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public void appendLinesToBuilder(StringBuilder builder) { | 
|  | assert this.builder == null; | 
|  | assert this.currentColumn == -1; | 
|  | this.builder = builder; | 
|  | formatParseFlags(); | 
|  | this.builder = null; | 
|  | this.currentColumn = -1; | 
|  | } | 
|  |  | 
|  | public static void main(String[] args) { | 
|  | D8.main(new String[] {"--help"}); | 
|  | } | 
|  | } |