2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Created by IntelliJ IDEA.
22 * To change template for new interface use
23 * Code Style | Class Templates options (Tools | IDE Options).
25 package com.intellij.codeInspection.ex;
27 import com.intellij.codeInspection.CommonProblemDescriptor;
28 import com.intellij.codeInspection.HTMLComposer;
29 import com.intellij.codeInspection.InspectionsBundle;
30 import com.intellij.codeInspection.export.HTMLExporter;
31 import com.intellij.codeInspection.lang.HTMLComposerExtension;
32 import com.intellij.codeInspection.lang.InspectionExtensionsFactory;
33 import com.intellij.codeInspection.reference.*;
34 import com.intellij.lang.Language;
35 import com.intellij.openapi.extensions.Extensions;
36 import com.intellij.openapi.util.Key;
37 import com.intellij.psi.PsiElement;
38 import com.intellij.psi.PsiFile;
39 import org.jetbrains.annotations.NonNls;
40 import org.jetbrains.annotations.Nullable;
43 import java.util.HashMap;
49 public abstract class HTMLComposerImpl extends HTMLComposer {
50 protected HTMLExporter myExporter;
51 private final int[] myListStack;
52 private int myListStackTop;
53 private final Map<Key, HTMLComposerExtension> myExtensions = new HashMap<Key, HTMLComposerExtension>();
54 private final Map<Language, HTMLComposerExtension> myLanguageExtensions = new HashMap<Language, HTMLComposerExtension>();
55 @NonNls protected static final String BR = "<br>";
56 @NonNls protected static final String NBSP = " ";
57 @NonNls protected static final String CODE_CLOSING = "</code>";
58 @NonNls protected static final String CODE_OPENING = "<code>";
59 @NonNls protected static final String FONT_CLOSING = "</font>";
60 @NonNls protected static final String B_OPENING = "<b>";
61 @NonNls protected static final String B_CLOSING = "</b>";
62 @NonNls protected static final String FONT_OPENING = "<font style=\"font-family:verdana;";
63 @NonNls protected static final String CLOSE_TAG = "\">";
64 @NonNls protected static final String A_HREF_OPENING = "<a HREF=\"";
65 @NonNls protected static final String A_CLOSING = "</a>";
67 protected HTMLComposerImpl() {
68 myListStack = new int[5];
70 for (InspectionExtensionsFactory factory : Extensions.getExtensions(InspectionExtensionsFactory.EP_NAME)) {
71 final HTMLComposerExtension extension = factory.createHTMLComposerExtension(this);
72 if (extension != null) {
73 myExtensions.put(extension.getID(), extension);
74 myLanguageExtensions.put(extension.getLanguage(), extension);
79 public abstract void compose(StringBuffer buf, RefEntity refEntity);
81 public void compose(StringBuffer buf, RefEntity refElement, CommonProblemDescriptor descriptor) {}
83 public void composeWithExporter(StringBuffer buf, RefEntity refEntity, HTMLExporter exporter) {
84 myExporter = exporter;
85 compose(buf, refEntity);
89 protected void genPageHeader(final StringBuffer buf, RefEntity refEntity) {
90 if (refEntity instanceof RefElement) {
91 RefElement refElement = (RefElement)refEntity;
93 appendHeading(buf, InspectionsBundle.message("inspection.offline.view.tool.display.name.title"));
95 appendAfterHeaderIndention(buf);
97 appendShortName(buf, refElement);
98 buf.append(BR).append(BR);
100 appendHeading(buf, InspectionsBundle.message("inspection.export.results.capitalized.location"));
102 appendAfterHeaderIndention(buf);
103 appendLocation(buf, refElement);
104 buf.append(BR).append(BR);
108 private void appendLocation(final StringBuffer buf, final RefElement refElement) {
109 buf.append(FONT_OPENING);
110 buf.append(CLOSE_TAG);
111 final HTMLComposerExtension extension = getLanguageExtension(refElement);
112 if (extension != null) {
113 extension.appendLocation(refElement, buf);
115 if (refElement instanceof RefFile){
116 buf.append(InspectionsBundle.message("inspection.export.results.file"));
118 appendElementReference(buf, refElement, false);
120 buf.append(FONT_CLOSING);
124 private HTMLComposerExtension getLanguageExtension(final RefElement refElement) {
125 final PsiElement element = refElement.getElement();
126 return element != null ? myLanguageExtensions.get(element.getLanguage()) : null;
129 private void appendShortName(final StringBuffer buf, RefElement refElement) {
130 final HTMLComposerExtension extension = getLanguageExtension(refElement);
131 if (extension != null) {
132 extension.appendShortName(refElement, buf);
134 refElement.accept(new RefVisitor() {
135 @Override public void visitFile(RefFile file) {
136 final PsiFile psiFile = file.getElement();
137 if (psiFile != null) {
138 buf.append(B_OPENING);
139 buf.append(psiFile.getName());
140 buf.append(B_CLOSING);
146 protected void appendQualifiedName(StringBuffer buf, RefEntity refEntity) {
147 if (refEntity == null) return;
150 while (!(refEntity instanceof RefProject)) {
151 if (qName.length() > 0) qName = "." + qName;
153 String name = refEntity.getName();
154 if (refEntity instanceof RefElement) {
155 final HTMLComposerExtension extension = getLanguageExtension((RefElement)refEntity);
156 if (extension != null) {
157 name = extension.getQualifiedName(refEntity);
161 qName = name + qName;
162 refEntity = refEntity.getOwner();
168 public void appendElementReference(final StringBuffer buf, RefElement refElement) {
169 appendElementReference(buf, refElement, true);
172 public void appendElementReference(final StringBuffer buf, RefElement refElement, String linkText, @NonNls String frameName) {
173 if (myExporter == null) {
174 final URL url = ((RefElementImpl)refElement).getURL();
176 appendElementReference(buf, url.toString(), linkText, frameName);
180 appendElementReference(buf, myExporter.getURL(refElement), linkText, frameName);
184 public void appendElementReference(final StringBuffer buf, String url, String linkText, @NonNls String frameName) {
185 buf.append(A_HREF_OPENING);
187 if (frameName != null) {
188 @NonNls final String target = "\" target=\"";
190 buf.append(frameName);
194 buf.append(linkText);
195 buf.append(A_CLOSING);
198 protected void appendQuickFix(@NonNls final StringBuffer buf, String text, int index) {
199 if (myExporter == null) {
200 buf.append(FONT_OPENING);
201 buf.append(CLOSE_TAG);
202 buf.append("<a HREF=\"file://bred.txt#invoke:").append(index);
205 buf.append("</a></font>");
209 public void appendElementReference(final StringBuffer buf, RefElement refElement, boolean isPackageIncluded) {
210 final HTMLComposerExtension extension = getLanguageExtension(refElement);
212 if (extension != null) {
213 extension.appendReferencePresentation(refElement, buf, isPackageIncluded);
214 } else if (refElement instanceof RefFile) {
215 buf.append(HTMLComposerImpl.A_HREF_OPENING);
217 if (myExporter == null) {
218 buf.append(((RefElementImpl)refElement).getURL());
221 buf.append(myExporter.getURL(refElement));
225 buf.append(refElement.getName());
226 buf.append(HTMLComposerImpl.A_CLOSING);
230 public String composeNumereables(int n, String statement, String singleEnding, String multipleEnding) {
231 final StringBuffer buf = new StringBuffer();
234 buf.append(statement);
236 if (n % 10 == 1 && n % 100 != 11) {
237 buf.append(singleEnding);
240 buf.append(multipleEnding);
242 return buf.toString();
245 public void appendElementInReferences(StringBuffer buf, RefElement refElement) {
246 if (refElement.getInReferences().size() > 0) {
247 appendHeading(buf, InspectionsBundle.message("inspection.export.results.used.from"));
249 for (RefElement refCaller : refElement.getInReferences()) {
250 appendListItem(buf, refCaller);
256 public void appendElementOutReferences(StringBuffer buf, RefElement refElement) {
257 if (refElement.getOutReferences().size() > 0) {
259 appendHeading(buf, InspectionsBundle.message("inspection.export.results.uses"));
261 for (RefElement refCallee : refElement.getOutReferences()) {
262 appendListItem(buf, refCallee);
268 public void appendListItem(StringBuffer buf, RefElement refElement) {
270 buf.append(FONT_OPENING);
271 buf.append(CLOSE_TAG);
272 appendElementReference(buf, refElement, true);
273 appendAdditionalListItemInfo(buf, refElement);
274 buf.append(FONT_CLOSING);
278 protected void appendAdditionalListItemInfo(StringBuffer buf, RefElement refElement) {
279 // Default appends nothing.
282 protected void appendResolution(StringBuffer buf, InspectionTool tool, RefEntity where) {
283 if (myExporter != null) return;
284 if (where instanceof RefElement && !where.isValid()) return;
285 QuickFixAction[] quickFixes = tool.getQuickFixes(new RefEntity[] {where});
286 if (quickFixes != null) {
287 boolean listStarted = false;
288 for (int i = 0; i < quickFixes.length; i++) {
289 QuickFixAction quickFix = quickFixes[i];
290 final String text = quickFix.getText(where);
291 if (text == null) continue;
293 appendHeading(buf, InspectionsBundle.message("inspection.problem.resolution"));
298 appendQuickFix(buf, text, i);
308 public void startList(@NonNls final StringBuffer buf) {
311 myListStack[myListStackTop] = 0;
314 public void doneList(@NonNls StringBuffer buf) {
316 if (myListStack[myListStackTop] != 0) {
317 buf.append("<table cellpadding=\"0\" border=\"0\" cellspacing=\"0\"><tr><td> </td></tr></table>");
322 public void startListItem(@NonNls StringBuffer buf) {
323 myListStack[myListStackTop]++;
327 public static void doneListItem(@NonNls StringBuffer buf) {
331 public void appendNoProblems(StringBuffer buf) {
333 appendAfterHeaderIndention(buf);
334 buf.append(B_OPENING);
335 buf.append(InspectionsBundle.message("inspection.export.results.no.problems.found"));
336 buf.append(B_CLOSING).append(BR);
339 public <T> T getExtension(final Key<T> key) {
340 return (T)myExtensions.get(key);