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 buf.append(B_OPENING);
138 buf.append(psiFile.getName());
139 buf.append(B_CLOSING);
144 protected void appendQualifiedName(StringBuffer buf, RefEntity refEntity) {
145 if (refEntity == null) return;
148 while (!(refEntity instanceof RefProject)) {
149 if (qName.length() > 0) qName = "." + qName;
151 String name = refEntity.getName();
152 if (refEntity instanceof RefElement) {
153 final HTMLComposerExtension extension = getLanguageExtension((RefElement)refEntity);
154 if (extension != null) {
155 name = extension.getQualifiedName(refEntity);
159 qName = name + qName;
160 refEntity = refEntity.getOwner();
166 public void appendElementReference(final StringBuffer buf, RefElement refElement) {
167 appendElementReference(buf, refElement, true);
170 public void appendElementReference(final StringBuffer buf, RefElement refElement, String linkText, @NonNls String frameName) {
171 if (myExporter == null) {
172 final URL url = ((RefElementImpl)refElement).getURL();
174 appendElementReference(buf, url.toString(), linkText, frameName);
178 appendElementReference(buf, myExporter.getURL(refElement), linkText, frameName);
182 public void appendElementReference(final StringBuffer buf, String url, String linkText, @NonNls String frameName) {
183 buf.append(A_HREF_OPENING);
185 if (frameName != null) {
186 @NonNls final String target = "\" target=\"";
188 buf.append(frameName);
192 buf.append(linkText);
193 buf.append(A_CLOSING);
196 protected void appendQuickFix(@NonNls final StringBuffer buf, String text, int index) {
197 if (myExporter == null) {
198 buf.append(FONT_OPENING);
199 buf.append(CLOSE_TAG);
200 buf.append("<a HREF=\"file://bred.txt#invoke:").append(index);
203 buf.append("</a></font>");
207 public void appendElementReference(final StringBuffer buf, RefElement refElement, boolean isPackageIncluded) {
208 final HTMLComposerExtension extension = getLanguageExtension(refElement);
210 if (extension != null) {
211 extension.appendReferencePresentation(refElement, buf, isPackageIncluded);
212 } else if (refElement instanceof RefFile) {
213 buf.append(HTMLComposerImpl.A_HREF_OPENING);
215 if (myExporter == null) {
216 buf.append(((RefElementImpl)refElement).getURL());
219 buf.append(myExporter.getURL(refElement));
223 buf.append(refElement.getName());
224 buf.append(HTMLComposerImpl.A_CLOSING);
228 public String composeNumereables(int n, String statement, String singleEnding, String multipleEnding) {
229 final StringBuffer buf = new StringBuffer();
232 buf.append(statement);
234 if (n % 10 == 1 && n % 100 != 11) {
235 buf.append(singleEnding);
238 buf.append(multipleEnding);
240 return buf.toString();
243 public void appendElementInReferences(StringBuffer buf, RefElement refElement) {
244 if (refElement.getInReferences().size() > 0) {
245 appendHeading(buf, InspectionsBundle.message("inspection.export.results.used.from"));
247 for (RefElement refCaller : refElement.getInReferences()) {
248 appendListItem(buf, refCaller);
254 public void appendElementOutReferences(StringBuffer buf, RefElement refElement) {
255 if (refElement.getOutReferences().size() > 0) {
257 appendHeading(buf, InspectionsBundle.message("inspection.export.results.uses"));
259 for (RefElement refCallee : refElement.getOutReferences()) {
260 appendListItem(buf, refCallee);
266 public void appendListItem(StringBuffer buf, RefElement refElement) {
268 buf.append(FONT_OPENING);
269 buf.append(CLOSE_TAG);
270 appendElementReference(buf, refElement, true);
271 appendAdditionalListItemInfo(buf, refElement);
272 buf.append(FONT_CLOSING);
276 protected void appendAdditionalListItemInfo(StringBuffer buf, RefElement refElement) {
277 // Default appends nothing.
280 protected void appendResolution(StringBuffer buf, InspectionTool tool, RefEntity where) {
281 if (myExporter != null) return;
282 if (where instanceof RefElement && !where.isValid()) return;
283 QuickFixAction[] quickFixes = tool.getQuickFixes(new RefEntity[] {where});
284 if (quickFixes != null) {
285 boolean listStarted = false;
286 for (int i = 0; i < quickFixes.length; i++) {
287 QuickFixAction quickFix = quickFixes[i];
288 final String text = quickFix.getText(where);
289 if (text == null) continue;
291 appendHeading(buf, InspectionsBundle.message("inspection.problem.resolution"));
296 appendQuickFix(buf, text, i);
306 public void startList(@NonNls final StringBuffer buf) {
309 myListStack[myListStackTop] = 0;
312 public void doneList(@NonNls StringBuffer buf) {
314 if (myListStack[myListStackTop] != 0) {
315 buf.append("<table cellpadding=\"0\" border=\"0\" cellspacing=\"0\"><tr><td> </td></tr></table>");
320 public void startListItem(@NonNls StringBuffer buf) {
321 myListStack[myListStackTop]++;
325 public static void doneListItem(@NonNls StringBuffer buf) {
329 public void appendNoProblems(StringBuffer buf) {
331 appendAfterHeaderIndention(buf);
332 buf.append(B_OPENING);
333 buf.append(InspectionsBundle.message("inspection.export.results.no.problems.found"));
334 buf.append(B_CLOSING).append(BR);
337 public <T> T getExtension(final Key<T> key) {
338 return (T)myExtensions.get(key);