blob: 0daaa84385be893f4c29d14993957cee8d1b0e4d [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.xml.util;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.xml.XmlBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class AddDtdDeclarationFix implements LocalQuickFix {
private final String myMessageKey;
private final String myElementDeclarationName;
private final String myReference;
public AddDtdDeclarationFix(
@PropertyKey(resourceBundle = XmlBundle.PATH_TO_BUNDLE) String messageKey,
@NotNull String elementDeclarationName,
@NotNull PsiReference reference) {
myMessageKey = messageKey;
myElementDeclarationName = elementDeclarationName;
myReference = reference.getCanonicalText();
}
@Override
@NotNull
public String getName() {
return XmlBundle.message(myMessageKey, myReference);
}
@Override
@NotNull
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiFile containingFile = element.getContainingFile();
if (!FileModificationService.getInstance().prepareFileForWrite(containingFile)) return;
@NonNls String prefixToInsert = "";
@NonNls String suffixToInsert = "";
final int UNDEFINED_OFFSET = -1;
int anchorOffset = UNDEFINED_OFFSET;
PsiElement anchor =
PsiTreeUtil.getParentOfType(element, XmlElementDecl.class, XmlAttlistDecl.class, XmlEntityDecl.class, XmlConditionalSection.class);
if (anchor != null) anchorOffset = anchor.getTextRange().getStartOffset();
if (anchorOffset == UNDEFINED_OFFSET && containingFile.getLanguage() == XMLLanguage.INSTANCE) {
XmlFile file = (XmlFile)containingFile;
final XmlProlog prolog = file.getDocument().getProlog();
assert prolog != null;
final XmlDoctype doctype = prolog.getDoctype();
final XmlMarkupDecl markupDecl;
if (doctype != null) {
markupDecl = doctype.getMarkupDecl();
}
else {
markupDecl = null;
}
if (doctype == null) {
final XmlTag rootTag = file.getDocument().getRootTag();
prefixToInsert = "<!DOCTYPE " + ((rootTag != null) ? rootTag.getName() : "null");
suffixToInsert = ">\n";
}
if (markupDecl == null) {
prefixToInsert += " [\n";
suffixToInsert = "]" + suffixToInsert;
if (doctype != null) {
anchorOffset = doctype.getTextRange().getEndOffset() - 1; // just before last '>'
}
else {
anchorOffset = prolog.getTextRange().getEndOffset();
}
}
}
if (anchorOffset == UNDEFINED_OFFSET) anchorOffset = element.getTextRange().getStartOffset();
OpenFileDescriptor openDescriptor = new OpenFileDescriptor(project, containingFile.getVirtualFile(), anchorOffset);
final Editor editor = FileEditorManager.getInstance(project).openTextEditor(openDescriptor, true);
final TemplateManager templateManager = TemplateManager.getInstance(project);
final Template t = templateManager.createTemplate("", "");
if (!prefixToInsert.isEmpty()) t.addTextSegment(prefixToInsert);
t.addTextSegment("<!" + myElementDeclarationName + " " + myReference + " ");
t.addEndVariable();
t.addTextSegment(">\n");
if (!suffixToInsert.isEmpty()) t.addTextSegment(suffixToInsert);
templateManager.startTemplate(editor, t);
}
}