15d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/*
25d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Copyright (C) 2014 Google, Inc.
35d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
45d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
55d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * you may not use this file except in compliance with the License.
65d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * You may obtain a copy of the License at
75d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
85d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
95d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Unless required by applicable law or agreed to in writing, software
115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * See the License for the specific language governing permissions and
145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * limitations under the License.
155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpackage dagger.internal.codegen.writer;
175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.collect.AbstractIterator;
195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.io.IOException;
205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.Iterator;
215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinfinal class IndentingAppendable implements Appendable {
235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private final String indentation;
245d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private final Appendable delegate;
255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private boolean requiresIndent = true;
265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  IndentingAppendable(Appendable delegate) {
285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    this("  ", delegate);
295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  IndentingAppendable(String indentation, Appendable delegate) {
325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    this.indentation = indentation;
335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    this.delegate = delegate;
345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Override
375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public Appendable append(CharSequence csq) throws IOException {
385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return append(csq, 0, csq.length());
395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
405d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Override
425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public Appendable append(CharSequence csq, int start, int end) throws IOException {
435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    Iterator<CharSequence> lines = lines(csq, start, end);
445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    while (lines.hasNext()) {
455d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      CharSequence line = lines.next();
465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      maybeIndent();
475d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      delegate.append(line);
485d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      if (line.charAt(line.length() - 1) == '\n') {
495d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        requiresIndent = true;
505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
525d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return this;
535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
545d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
555d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Override
565d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public Appendable append(char c) throws IOException {
575d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    maybeIndent();
585d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    delegate.append(c);
595d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    if (c == '\n') {
605d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      requiresIndent = true;
615d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
625d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return this;
635d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  void maybeIndent() throws IOException {
665d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    if (requiresIndent) {
675d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      delegate.append(indentation);
685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
695d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    requiresIndent = false;
705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
715d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  private static Iterator<CharSequence> lines(
735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      final CharSequence csq, final int start, final int end) {
745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    return new AbstractIterator<CharSequence>() {
755d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      int index = start;
765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
775d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      @Override protected CharSequence computeNext() {
785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        int nextStart = index;
795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        while (index < end && csq.charAt(index) != '\n') {
805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          index++;
815d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        if (index < end && csq.charAt(index) == '\n') {
835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          index++;
845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        }
855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        int nextEnd = index;
865d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        return nextStart >= end
875d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin            ? endOfData()
885d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin            : csq.subSequence(nextStart, nextEnd);
895d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      }
905d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    };
915d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
925d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin}
93