1/* 2 * Copyright (C) 2011 The Android Open Source Project 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 17package com.android.tools.lint; 18 19import com.android.tools.lint.detector.api.Location; 20import com.android.tools.lint.detector.api.Position; 21import com.android.tools.lint.detector.api.Severity; 22import com.google.common.annotations.Beta; 23 24import java.io.IOException; 25import java.io.Writer; 26import java.util.List; 27 28/** 29 * A reporter which emits lint warnings as plain text strings 30 * <p> 31 * <b>NOTE: This is not a public or final API; if you rely on this be prepared 32 * to adjust your code for the next tools release.</b> 33 */ 34@Beta 35public class TextReporter extends Reporter { 36 private final Writer mWriter; 37 private final boolean mClose; 38 39 /** 40 * Constructs a new {@link TextReporter} 41 * 42 * @param client the client 43 * @param writer the writer to write into 44 * @param close whether the writer should be closed when done 45 */ 46 public TextReporter(Main client, Writer writer, boolean close) { 47 super(client, null); 48 mWriter = writer; 49 mClose = close; 50 } 51 52 @Override 53 public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException { 54 boolean abbreviate = mClient.getDriver().isAbbreviating(); 55 56 StringBuilder output = new StringBuilder(issues.size() * 200); 57 if (issues.size() == 0) { 58 mWriter.write('\n'); 59 mWriter.write("No issues found."); 60 mWriter.write('\n'); 61 mWriter.flush(); 62 } else { 63 for (Warning warning : issues) { 64 int startLength = output.length(); 65 66 if (warning.path != null) { 67 output.append(warning.path); 68 output.append(':'); 69 70 if (warning.line >= 0) { 71 output.append(Integer.toString(warning.line + 1)); 72 output.append(':'); 73 } 74 if (startLength < output.length()) { 75 output.append(' '); 76 } 77 } 78 79 Severity severity = warning.severity; 80 if (severity == Severity.FATAL) { 81 // Treat the fatal error as an error such that we don't display 82 // both "Fatal:" and "Error:" etc in the error output. 83 severity = Severity.ERROR; 84 } 85 output.append(severity.getDescription()); 86 output.append(':'); 87 output.append(' '); 88 89 output.append(warning.message); 90 if (warning.issue != null) { 91 output.append(' ').append('['); 92 output.append(warning.issue.getId()); 93 output.append(']'); 94 } 95 96 output.append('\n'); 97 98 if (warning.errorLine != null && warning.errorLine.length() > 0) { 99 output.append(warning.errorLine); 100 } 101 102 if (warning.location != null && warning.location.getSecondary() != null) { 103 Location location = warning.location.getSecondary(); 104 while (location != null) { 105 if (location.getMessage() != null 106 && location.getMessage().length() > 0) { 107 output.append(" "); //$NON-NLS-1$ 108 String path = mClient.getDisplayPath(warning.project, 109 location.getFile()); 110 output.append(path); 111 112 Position start = location.getStart(); 113 if (start != null) { 114 int line = start.getLine(); 115 if (line >= 0) { 116 output.append(':'); 117 output.append(Integer.toString(line + 1)); 118 } 119 } 120 121 if (location.getMessage() != null 122 && location.getMessage().length() > 0) { 123 output.append(':'); 124 output.append(' '); 125 output.append(location.getMessage()); 126 } 127 128 output.append('\n'); 129 } 130 131 location = location.getSecondary(); 132 } 133 134 if (!abbreviate) { 135 location = warning.location.getSecondary(); 136 StringBuilder sb = new StringBuilder(); 137 sb.append("Also affects: "); 138 int begin = sb.length(); 139 while (location != null) { 140 if (location.getMessage() == null 141 || location.getMessage().length() > 0) { 142 if (sb.length() > begin) { 143 sb.append(", "); 144 } 145 146 String path = mClient.getDisplayPath(warning.project, 147 location.getFile()); 148 sb.append(path); 149 150 Position start = location.getStart(); 151 if (start != null) { 152 int line = start.getLine(); 153 if (line >= 0) { 154 sb.append(':'); 155 sb.append(Integer.toString(line + 1)); 156 } 157 } 158 } 159 160 location = location.getSecondary(); 161 } 162 String wrapped = Main.wrap(sb.toString(), Main.MAX_LINE_WIDTH, " "); //$NON-NLS-1$ 163 output.append(wrapped); 164 } 165 } 166 } 167 168 mWriter.write(output.toString()); 169 170 mWriter.write(String.format("%1$d errors, %2$d warnings", 171 errorCount, warningCount)); 172 mWriter.write('\n'); 173 mWriter.flush(); 174 if (mClose) { 175 mWriter.close(); 176 } 177 } 178 } 179}