Home | History | Annotate | Download | only in writer
      1 /*
      2  * Copyright (C) 2014 Google, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package dagger.internal.codegen.writer;
     17 
     18 import com.google.common.collect.AbstractIterator;
     19 import java.io.IOException;
     20 import java.util.Iterator;
     21 
     22 final class IndentingAppendable implements Appendable {
     23   private final String indentation;
     24   private final Appendable delegate;
     25   private boolean requiresIndent = true;
     26 
     27   IndentingAppendable(Appendable delegate) {
     28     this("  ", delegate);
     29   }
     30 
     31   IndentingAppendable(String indentation, Appendable delegate) {
     32     this.indentation = indentation;
     33     this.delegate = delegate;
     34   }
     35 
     36   @Override
     37   public Appendable append(CharSequence csq) throws IOException {
     38     return append(csq, 0, csq.length());
     39   }
     40 
     41   @Override
     42   public Appendable append(CharSequence csq, int start, int end) throws IOException {
     43     Iterator<CharSequence> lines = lines(csq, start, end);
     44     while (lines.hasNext()) {
     45       CharSequence line = lines.next();
     46       maybeIndent();
     47       delegate.append(line);
     48       if (line.charAt(line.length() - 1) == '\n') {
     49         requiresIndent = true;
     50       }
     51     }
     52     return this;
     53   }
     54 
     55   @Override
     56   public Appendable append(char c) throws IOException {
     57     maybeIndent();
     58     delegate.append(c);
     59     if (c == '\n') {
     60       requiresIndent = true;
     61     }
     62     return this;
     63   }
     64 
     65   void maybeIndent() throws IOException {
     66     if (requiresIndent) {
     67       delegate.append(indentation);
     68     }
     69     requiresIndent = false;
     70   }
     71 
     72   private static Iterator<CharSequence> lines(
     73       final CharSequence csq, final int start, final int end) {
     74     return new AbstractIterator<CharSequence>() {
     75       int index = start;
     76 
     77       @Override protected CharSequence computeNext() {
     78         int nextStart = index;
     79         while (index < end && csq.charAt(index) != '\n') {
     80           index++;
     81         }
     82         if (index < end && csq.charAt(index) == '\n') {
     83           index++;
     84         }
     85         int nextEnd = index;
     86         return nextStart >= end
     87             ? endOfData()
     88             : csq.subSequence(nextStart, nextEnd);
     89       }
     90     };
     91   }
     92 }
     93