com.android.tools.lint.detector.api.Severity Java Examples

The following examples show how to use com.android.tools.lint.detector.api.Severity. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DefaultConfigurationTest.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
public void test() throws Exception {
    DefaultConfiguration configuration = getConfiguration(""
            + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            + "<lint>\n"
            + "    <issue id=\"ObsoleteLayoutParam\">\n"
            + "        <ignore path=\"res/layout-xlarge/activation.xml\" />\n"
            + "    </issue>\n"
            + "    <issue id=\"FloatMath\" severity=\"ignore\" />\n"
            + "    <issue id=\"FieldGetter\" severity=\"error\" />\n"
            + "    <issue id=\"SdCardPath,ContentDescription\" severity=\"ignore\" />"
            + "    <issue id=\"NewApi\">\n"
            + "        <ignore path=\"res/layout-xlarge\" />\n"
            + "    </issue>\n"
            + "</lint>");
    assertTrue(configuration.isEnabled(ObsoleteLayoutParamsDetector.ISSUE));
    assertFalse(configuration.isEnabled(SdCardDetector.ISSUE));
    assertFalse(configuration.isEnabled(MathDetector.ISSUE));
    assertFalse(configuration.isEnabled(AccessibilityDetector.ISSUE));
    assertEquals(Severity.IGNORE, configuration.getSeverity(AccessibilityDetector.ISSUE));
    assertEquals(Severity.WARNING, AccessibilityDetector.ISSUE.getDefaultSeverity());
    assertEquals(Severity.WARNING, FieldGetterDetector.ISSUE.getDefaultSeverity());
    assertEquals(Severity.ERROR, configuration.getSeverity(FieldGetterDetector.ISSUE));
    assertEquals(Severity.IGNORE, configuration.getSeverity(MathDetector.ISSUE));
}
 
Example #2
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
/** Returns the configuration used by this client */
Configuration getConfiguration() {
    if (mConfiguration == null) {
        File configFile = mFlags.getDefaultConfiguration();
        if (configFile != null) {
            if (!configFile.exists()) {
                if (sAlreadyWarned == null || !sAlreadyWarned.contains(configFile)) {
                    log(Severity.ERROR, null,
                            "Warning: Configuration file %1$s does not exist", configFile);
                }
                if (sAlreadyWarned == null) {
                    sAlreadyWarned = Sets.newHashSet();
                }
                sAlreadyWarned.add(configFile);
            }
            mConfiguration = createConfigurationFromFile(configFile);
        }
    }

    return mConfiguration;
}
 
Example #3
Source File: ApiLookupTest.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void log(
        @NonNull Severity severity,
        @Nullable Throwable exception,
        @Nullable String format,
        @Nullable Object... args) {
    if (format != null) {
        mLogBuffer.append(String.format(format, args));
        mLogBuffer.append('\n');
    }
    if (exception != null) {
        StringWriter writer = new StringWriter();
        exception.printStackTrace(new PrintWriter(writer));
        mLogBuffer.append(writer.toString());
        mLogBuffer.append('\n');
    }
}
 
Example #4
Source File: LintOptions.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
/**
 * An optional map of severity overrides. The map maps from issue id's to the corresponding
 * severity to use, which must be "fatal", "error", "warning", or "ignore".
 *
 * @return a map of severity overrides, or null. The severities are one of the constants
 * {@link #SEVERITY_FATAL}, {@link #SEVERITY_ERROR}, {@link #SEVERITY_WARNING},
 * {@link #SEVERITY_INFORMATIONAL}, {@link #SEVERITY_IGNORE}
 */
@Override
@Nullable
public Map<String, Integer> getSeverityOverrides() {
    if (severities == null || severities.isEmpty()) {
        return null;
    }

    Map<String, Integer> map =
            Maps.newHashMapWithExpectedSize(severities.size());
    for (Map.Entry<String, Severity> entry : severities.entrySet()) {
        map.put(entry.getKey(), convert(entry.getValue()));
    }

    return map;
}
 
Example #5
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@NonNull
@Override
public Severity getSeverity(@NonNull Issue issue) {
    Severity severity = computeSeverity(issue);

    if (mFatalOnly && severity != Severity.FATAL) {
        return Severity.IGNORE;
    }

    if (mFlags.isWarningsAsErrors() && severity == Severity.WARNING) {
        severity = Severity.ERROR;
    }

    if (mFlags.isIgnoreWarnings() && severity == Severity.WARNING) {
        severity = Severity.IGNORE;
    }

    return severity;
}
 
Example #6
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void log(
        @NonNull Severity severity,
        @Nullable Throwable exception,
        @Nullable String format,
        @Nullable Object... args) {
    System.out.flush();
    if (!mFlags.isQuiet()) {
        // Place the error message on a line of its own since we're printing '.' etc
        // with newlines during analysis
        System.err.println();
    }
    if (format != null) {
        System.err.println(String.format(format, args));
    }
    if (exception != null) {
        exception.printStackTrace();
    }
}
 
Example #7
Source File: DefaultConfiguration.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
@NonNull
public Severity getSeverity(@NonNull Issue issue) {
    ensureInitialized();

    Severity severity = mSeverity.get(issue.getId());
    if (severity == null) {
        severity = mSeverity.get(VALUE_ALL);
    }

    if (severity != null) {
        return severity;
    }

    if (mParent != null) {
        return mParent.getSeverity(issue);
    }

    return getDefaultSeverity(issue);
}
 
Example #8
Source File: LintDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
@NonNull
protected Severity getDefaultSeverity(@NonNull Issue issue) {
    // In unit tests, include issues that are ignored by default
    Severity severity = super.getDefaultSeverity(issue);
    if (severity == Severity.IGNORE) {
        if (issue.getDefaultSeverity() != Severity.IGNORE) {
            return issue.getDefaultSeverity();
        }
        return Severity.WARNING;
    }
    return severity;
}
 
Example #9
Source File: LintDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
protected void checkReportedError(
        @NonNull Context context,
        @NonNull Issue issue,
        @NonNull Severity severity,
        @Nullable Location location,
        @NonNull String message) {
}
 
Example #10
Source File: LintCliXmlParserTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void report(
        @NonNull Context context,
        @NonNull Issue issue,
        @NonNull Severity severity,
        @Nullable Location location,
        @NonNull String message,
        @NonNull TextFormat format) {
    System.out.println(location + ":" + message);
}
 
Example #11
Source File: DuplicateResourceDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
protected void checkReportedError(@NonNull Context context, @NonNull Issue issue,
        @NonNull Severity severity, @Nullable Location location, @NonNull String message) {
    if (issue == DuplicateResourceDetector.TYPE_MISMATCH) {
        assertNotNull(message, DuplicateResourceDetector.getExpectedType(message, TEXT));
    }
}
 
Example #12
Source File: GridLayoutDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
protected void checkReportedError(@NonNull Context context, @NonNull Issue issue,
        @NonNull Severity severity, @Nullable Location location, @NonNull String message) {
    if (message.contains("with v7 GridLayout")) {
        assertNotNull(message, getOldValue(message, TEXT));
        assertNotNull(message, getNewValue(message, TEXT));
    }
}
 
Example #13
Source File: MissingClassDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
protected void checkReportedError(@NonNull Context context, @NonNull Issue issue,
        @NonNull Severity severity, @Nullable Location location, @NonNull String message) {
    if (issue == INNERCLASS) {
        assertNotNull(message, MissingClassDetector.getOldValue(issue, message, TEXT));
        assertNotNull(message, MissingClassDetector.getNewValue(issue, message, TEXT));
    }
}
 
Example #14
Source File: JarFileIssueRegistryTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
public void testCached() throws Exception {
    File targetDir = Files.createTempDir();
    File file1 = getTestfile(targetDir, "rules/appcompat.jar.data");
    File file2 = getTestfile(targetDir, "apicheck/unsupported.jar.data");
    assertTrue(file1.getPath(), file1.exists());
    final StringWriter mLoggedWarnings = new StringWriter();
    TestLintClient client = new TestLintClient() {
        @Override
        public void log(@NonNull Severity severity, @Nullable Throwable exception,
                @Nullable String format, @Nullable Object... args) {
            if (format != null) {
                mLoggedWarnings.append(String.format(format, args));
            }
        }

    };
    IssueRegistry registry1 = JarFileIssueRegistry.get(client, file1);
    IssueRegistry registry2 = JarFileIssueRegistry.get(client, new File(file1.getPath()));
    assertSame(registry1, registry2);
    IssueRegistry registry3 = JarFileIssueRegistry.get(client, file2);
    assertNotSame(registry1, registry3);

    assertEquals(1, registry1.getIssues().size());
    assertEquals("AppCompatMethod", registry1.getIssues().get(0).getId());

    assertEquals(
            "Custom lint rule jar " + file2.getPath() + " does not contain a valid "
                    + "registry manifest key (Lint-Registry).\n"
                    + "Either the custom jar is invalid, or it uses an outdated API not "
                    + "supported this lint client", mLoggedWarnings.toString());
}
 
Example #15
Source File: DefaultConfigurationTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
public void testWriteLintXml() throws Exception {
    DefaultConfiguration configuration = getConfiguration(""
            + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            + "<lint>\n"
            + "  <issue id=\"ObsoleteLayoutParam\">\n"
            + "      <ignore path=\"res/layout-xlarge/activation.xml\" />\n"
            + "      <ignore path=\"res\\layout-xlarge\\activation2.xml\" />\n"
            + "      <ignore regexp=\"res/.*/activation2.xml\" />\n"
            + "  </issue>\n"
            + "  <issue id=\"FloatMath\" severity=\"ignore\" />\n"
            + "  <issue id=\"SdCardPath\" severity=\"ignore\" />"
            + "</lint>");
    configuration.startBulkEditing();
    configuration.setSeverity(TypoDetector.ISSUE, Severity.ERROR);
    configuration.ignore(TypoDetector.ISSUE, new File("foo/bar/Baz.java"));
    configuration.finishBulkEditing();
    String updated = Files.toString(configuration.getConfigFile(), Charsets.UTF_8);
    assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            + "<lint>\n"
            + "    <issue id=\"FloatMath\" severity=\"ignore\" />\n"
            + "    <issue id=\"ObsoleteLayoutParam\">\n"
            + "        <ignore path=\"res/layout-xlarge/activation.xml\" />\n"
            + "        <ignore path=\"res/layout-xlarge/activation2.xml\" />\n"
            + "        <ignore regexp=\"res/.*/activation2.xml\" />\n"
            + "    </issue>\n"
            + "    <issue id=\"SdCardPath\" severity=\"ignore\" />\n"
            + "    <issue id=\"Typos\" severity=\"error\">\n"
            + "        <ignore path=\"foo/bar/Baz.java\" />\n"
            + "    </issue>\n"
            + "</lint>",
            updated);
}
 
Example #16
Source File: GradleDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
protected void checkReportedError(@NonNull Context context, @NonNull Issue issue,
        @NonNull Severity severity, @Nullable Location location, @NonNull String message) {
    if (issue == DEPENDENCY && message.startsWith("Using the appcompat library when ")) {
        // No data embedded in this specific message
        return;
    }

    // Issues we're supporting getOldFrom
    if (issue == DEPENDENCY
            || issue == STRING_INTEGER
            || issue == DEPRECATED
            || issue == PLUS) {
        assertNotNull("Could not extract message tokens from " + message,
                GradleDetector.getOldValue(issue, message, TEXT));
    }

    if (issue == DEPENDENCY
            || issue == STRING_INTEGER
            || issue == DEPRECATED) {
        assertNotNull("Could not extract message tokens from " + message,
                GradleDetector.getNewValue(issue, message, TEXT));
    }

    if (issue == COMPATIBILITY) {
        if (message.startsWith("Version ")) {
            assertNotNull("Could not extract message tokens from " + message,
                    GradleDetector.getNewValue(issue, message, TEXT));
        }
    }
}
 
Example #17
Source File: ApiDetectorTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
protected void checkReportedError(@NonNull Context context, @NonNull Issue issue,
        @NonNull Severity severity, @Nullable Location location, @NonNull String message) {
    if (issue == UNSUPPORTED || issue == INLINED) {
        int requiredVersion = ApiDetector.getRequiredVersion(issue, message, TEXT);
        assertTrue("Could not extract message tokens from " + message,
                requiredVersion >= 1 && requiredVersion <= SdkVersionInfo.HIGHEST_KNOWN_API);
    }
}
 
Example #18
Source File: DefaultConfigurationTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
public void testMessagePatternIgnore() throws Exception {
    File projectDir = getProjectDir(null,
            "res/layout/onclick.xml=>res/layout/onclick.xml"
    );
    LintClient client = new TestLintClient();
    Project project = Project.create(client, projectDir, projectDir);
    LintDriver driver = new LintDriver(new BuiltinIssueRegistry(), client);
    File file = new File(projectDir,
            "res" + File.separator + "layout" + File.separator + "onclick.xml");
    assertTrue(file.exists());
    Context plainContext = new Context(driver, project, project, file);
    Location location = Location.create(file);

    assertEquals(Severity.WARNING, ObsoleteLayoutParamsDetector.ISSUE.getDefaultSeverity());

    DefaultConfiguration configuration = getConfiguration(""
            + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            + "<lint>\n"
            + "    <issue id=\"ObsoleteLayoutParam\">\n"
            + "        <ignore regexp=\"sample_icon\\.gif\" />\n"
            + "        <ignore regexp=\"javax\\.swing\" />\n"
            + "    </issue>\n"
            + "</lint>");

    assertFalse(configuration.isIgnored(plainContext, ObsoleteLayoutParamsDetector.ISSUE,
            location,
            "Missing the following drawables in drawable-hdpi: some_random.gif (found in drawable-mdpi)"));
    assertTrue(configuration.isIgnored(plainContext, ObsoleteLayoutParamsDetector.ISSUE,
            location,
            "Missing the following drawables in drawable-hdpi: sample_icon.gif (found in drawable-mdpi)"));

    assertFalse(configuration.isIgnored(plainContext, ObsoleteLayoutParamsDetector.ISSUE,
            location,
            "Invalid package reference in library; not included in Android: java.awt. Referenced from test.pkg.LibraryClass."));
    assertTrue(configuration.isIgnored(plainContext, ObsoleteLayoutParamsDetector.ISSUE,
            location,
            "Invalid package reference in library; not included in Android: javax.swing. Referenced from test.pkg.LibraryClass."));
}
 
Example #19
Source File: ProjectTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void log(@NonNull Severity severity, @Nullable Throwable exception,
        @Nullable String format, @Nullable Object... args) {
    assertNotNull(format);
    mLog.append(severity.getDescription()).append(": ");
    mLog.append(String.format(format, args));
}
 
Example #20
Source File: LintOptions.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static Severity convert(int s) {
    switch (s) {
        case com.android.builder.model.LintOptions.SEVERITY_FATAL:
            return FATAL;
        case com.android.builder.model.LintOptions.SEVERITY_ERROR:
            return ERROR;
        case com.android.builder.model.LintOptions.SEVERITY_WARNING:
            return WARNING;
        case com.android.builder.model.LintOptions.SEVERITY_INFORMATIONAL:
            return INFORMATIONAL;
        case com.android.builder.model.LintOptions.SEVERITY_IGNORE:
        default:
            return IGNORE;
    }
}
 
Example #21
Source File: LintOptions.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static int convert(Severity s) {
    switch (s) {
        case FATAL:
            return com.android.builder.model.LintOptions.SEVERITY_FATAL;
        case ERROR:
            return com.android.builder.model.LintOptions.SEVERITY_ERROR;
        case WARNING:
            return com.android.builder.model.LintOptions.SEVERITY_WARNING;
        case INFORMATIONAL:
            return com.android.builder.model.LintOptions.SEVERITY_INFORMATIONAL;
        case IGNORE:
        default:
            return com.android.builder.model.LintOptions.SEVERITY_IGNORE;
    }
}
 
Example #22
Source File: DefaultConfiguration.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void setSeverity(@NonNull Issue issue, @Nullable Severity severity) {
    ensureInitialized();

    String id = issue.getId();
    if (severity == null) {
        mSeverity.remove(id);
    } else {
        mSeverity.put(id, severity);
    }

    if (!mBulkEditing) {
        writeConfig();
    }
}
 
Example #23
Source File: DefaultConfiguration.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@NonNull
protected Severity getDefaultSeverity(@NonNull Issue issue) {
    if (!issue.isEnabledByDefault()) {
        return Severity.IGNORE;
    }

    return issue.getDefaultSeverity();
}
 
Example #24
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@NonNull
@Override
protected Severity getDefaultSeverity(@NonNull Issue issue) {
    if (mFlags.isCheckAllWarnings()) {
        return issue.getDefaultSeverity();
    }

    return super.getDefaultSeverity(issue);
}
 
Example #25
Source File: LintDriver.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void report(
        @NonNull Context context,
        @NonNull Issue issue,
        @NonNull Severity severity,
        @Nullable Location location,
        @NonNull String message,
        @NonNull TextFormat format) {
    assert mCurrentProject != null;
    if (!mCurrentProject.getReportIssues()) {
        return;
    }

    Configuration configuration = context.getConfiguration();
    if (!configuration.isEnabled(issue)) {
        if (issue != IssueRegistry.PARSER_ERROR && issue != IssueRegistry.LINT_ERROR) {
            mDelegate.log(null, "Incorrect detector reported disabled issue %1$s",
                    issue.toString());
        }
        return;
    }

    if (configuration.isIgnored(context, issue, location, message)) {
        return;
    }

    if (severity == Severity.IGNORE) {
        return;
    }

    mDelegate.report(context, issue, severity, location, message, format);
}
 
Example #26
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private Severity computeSeverity(@NonNull Issue issue) {
    Severity severity = super.getSeverity(issue);

    String id = issue.getId();
    Set<String> suppress = mFlags.getSuppressedIds();
    if (suppress.contains(id)) {
        return Severity.IGNORE;
    }

    Severity manual = mFlags.getSeverityOverrides().get(id);
    if (manual != null) {
        return manual;
    }

    Set<String> enabled = mFlags.getEnabledIds();
    Set<String> check = mFlags.getExactCheckedIds();
    if (enabled.contains(id) || (check != null && check.contains(id))) {
        // Overriding default
        // Detectors shouldn't be returning ignore as a default severity,
        // but in case they do, force it up to warning here to ensure that
        // it's run
        if (severity == Severity.IGNORE) {
            severity = issue.getDefaultSeverity();
            if (severity == Severity.IGNORE) {
                severity = Severity.WARNING;
            }
        }

        return severity;
    }

    if (check != null && issue != LINT_ERROR && issue != PARSER_ERROR) {
        return Severity.IGNORE;
    }

    return severity;
}
 
Example #27
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
protected void reportNonExistingIssueId(@Nullable Project project, @NonNull String id) {
    String message = String.format("Unknown issue id \"%1$s\"", id);

    if (mDriver != null && project != null) {
        Location location = Location.create(project.getDir());
        if (!isSuppressed(IssueRegistry.LINT_ERROR)) {
            report(new Context(mDriver, project, project, project.getDir()),
                    IssueRegistry.LINT_ERROR,
                    project.getConfiguration(mDriver).getSeverity(IssueRegistry.LINT_ERROR),
                    location, message, TextFormat.RAW);
        }
    } else {
        log(Severity.ERROR, null, "Lint: %1$s", message);
    }
}
 
Example #28
Source File: IssueDetector.java    From aircon with MIT License 4 votes vote down vote up
protected static Issue createErrorIssue(String id, String briefDesc, String explanation) {
	return createIssue(id, briefDesc, explanation, Severity.ERROR);
}
 
Example #29
Source File: Warning.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
public Warning(Issue issue, String message, Severity severity, Project project) {
    this.issue = issue;
    this.message = message;
    this.severity = severity;
    this.project = project;
}
 
Example #30
Source File: HtmlReporter.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
private void writeIssueMetadata(Issue issue, Severity severity, String disabledBy)
        throws IOException {
    mWriter.write("<div class=\"metadata\">");               //$NON-NLS-1$

    if (mClient.getRegistry() instanceof BuiltinIssueRegistry) {
        boolean adtHasFix = QuickfixHandler.ADT.hasAutoFix(issue);
        boolean studioHasFix = QuickfixHandler.STUDIO.hasAutoFix(issue);
        if (adtHasFix || studioHasFix) {
            String adt = "Eclipse/ADT";
            String studio = "Android Studio/IntelliJ";
            String tools = adtHasFix && studioHasFix
                    ? (adt + " & " + studio) : studioHasFix ? studio : adt;
            mWriter.write("Note: This issue has an associated quickfix operation in " + tools);
            if (mFixUrl != null) {
                mWriter.write("&nbsp;<img alt=\"Fix\" border=\"0\" align=\"top\" src=\""); //$NON-NLS-1$
                mWriter.write(mFixUrl);
                mWriter.write("\" />\n");                            //$NON-NLS-1$
            }

            mWriter.write("<br>\n");
        }
    }

    if (disabledBy != null) {
        mWriter.write(String.format("Disabled By: %1$s<br/>\n", disabledBy));
    }

    mWriter.write("Priority: ");
    mWriter.write(String.format("%1$d / 10", issue.getPriority()));
    mWriter.write("<br/>\n");                                //$NON-NLS-1$
    mWriter.write("Category: ");
    mWriter.write(issue.getCategory().getFullName());
    mWriter.write("</div>\n");                               //$NON-NLS-1$

    mWriter.write("Severity: ");
    if (severity == Severity.ERROR || severity == Severity.FATAL) {
        mWriter.write("<span class=\"error\">");             //$NON-NLS-1$
    } else if (severity == Severity.WARNING) {
        mWriter.write("<span class=\"warning\">");           //$NON-NLS-1$
    } else {
        mWriter.write("<span>");                             //$NON-NLS-1$
    }
    appendEscapedText(severity.getDescription());
    mWriter.write("</span>");                                //$NON-NLS-1$

    mWriter.write("<div class=\"summary\">\n");              //$NON-NLS-1$
    mWriter.write("Explanation: ");
    String description = issue.getBriefDescription(HTML);
    mWriter.write(description);
    if (!description.isEmpty()
            && Character.isLetter(description.charAt(description.length() - 1))) {
        mWriter.write('.');
    }
    mWriter.write("</div>\n");                               //$NON-NLS-1$
    mWriter.write("<div class=\"explanation\">\n");          //$NON-NLS-1$
    String explanationHtml = issue.getExplanation(HTML);
    mWriter.write(explanationHtml);
    mWriter.write("\n</div>\n");                             //$NON-NLS-1$;
    List<String> moreInfo = issue.getMoreInfo();
    mWriter.write("<br/>");                                  //$NON-NLS-1$
    mWriter.write("<div class=\"moreinfo\">");               //$NON-NLS-1$
    mWriter.write("More info: ");
    int count = moreInfo.size();
    if (count > 1) {
        mWriter.write("<ul>");                               //$NON-NLS-1$
    }
    for (String uri : moreInfo) {
        if (count > 1) {
            mWriter.write("<li>");                           //$NON-NLS-1$
        }
        mWriter.write("<a href=\"");                         //$NON-NLS-1$
        mWriter.write(uri);
        mWriter.write("\">"    );                            //$NON-NLS-1$
        mWriter.write(uri);
        mWriter.write("</a>\n");                             //$NON-NLS-1$
    }
    if (count > 1) {
        mWriter.write("</ul>");                              //$NON-NLS-1$
    }
    mWriter.write("</div>");                                 //$NON-NLS-1$

    mWriter.write("<br/>");                                  //$NON-NLS-1$
    mWriter.write(String.format(
            "To suppress this error, use the issue id \"%1$s\" as explained in the " +
            "%2$sSuppressing Warnings and Errors%3$s section.",
            issue.getId(),
            "<a href=\"#SuppressInfo\">", "</a>"));          //$NON-NLS-1$ //$NON-NLS-2$
    mWriter.write("<br/>\n");
}