use of com.intellij.psi.templateLanguages.OuterLanguageElement in project intellij-community by JetBrains.
the class HtmlLocalInspectionTool method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new XmlElementVisitor() {
@Override
public void visitXmlToken(final XmlToken token) {
IElementType tokenType = token.getTokenType();
if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
PsiElement element = token.getPrevSibling();
while (element instanceof PsiWhiteSpace) element = element.getPrevSibling();
if (element instanceof XmlToken && ((XmlToken) element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
PsiElement parent = element.getParent();
if (parent instanceof XmlTag && !(token.getNextSibling() instanceof OuterLanguageElement)) {
XmlTag tag = (XmlTag) parent;
checkTag(tag, holder, isOnTheFly);
}
}
}
}
@Override
public void visitXmlAttribute(final XmlAttribute attribute) {
checkAttribute(attribute, holder, isOnTheFly);
}
};
}
use of com.intellij.psi.templateLanguages.OuterLanguageElement in project intellij-community by JetBrains.
the class XmlGtTypedHandler method beforeCharTyped.
@Override
public Result beforeCharTyped(final char c, final Project project, Editor editor, PsiFile editedFile, final FileType fileType) {
final WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
if (c == '>' && webEditorOptions != null && webEditorOptions.isAutomaticallyInsertClosingTag() && fileContainsXmlLanguage(editedFile)) {
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
FileViewProvider provider = editedFile.getViewProvider();
int offset = editor.getCaretModel().getOffset();
PsiElement element, elementAtCaret = null;
if (offset < editor.getDocument().getTextLength()) {
elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class);
if (element == null && offset > 0) {
// seems like a template language
// <xml_code><caret><outer_element>
elementAtCaret = element = provider.findElementAt(offset - 1, XMLLanguage.class);
}
if (!(element instanceof PsiWhiteSpace)) {
boolean nonAcceptableDelimiter = true;
if (element instanceof XmlToken) {
IElementType tokenType = ((XmlToken) element).getTokenType();
if (tokenType == XmlTokenType.XML_START_TAG_START || tokenType == XmlTokenType.XML_END_TAG_START) {
if (offset > 0) {
PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
if (previousElement instanceof XmlToken) {
tokenType = ((XmlToken) previousElement).getTokenType();
element = previousElement;
nonAcceptableDelimiter = false;
}
}
} else if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
if (element.getNextSibling() instanceof PsiErrorElement) {
nonAcceptableDelimiter = false;
}
}
if (tokenType == XmlTokenType.XML_TAG_END || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1) {
EditorModificationUtil.moveCaretRelatively(editor, 1);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
return Result.STOP;
}
}
if (nonAcceptableDelimiter)
return Result.CONTINUE;
} else {
// check if right after empty end
PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
if (previousElement instanceof XmlToken) {
final IElementType tokenType = ((XmlToken) previousElement).getTokenType();
if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
return Result.STOP;
}
}
}
PsiElement parent = element.getParent();
if (parent instanceof XmlText) {
final String text = parent.getText();
// check /
final int index = offset - parent.getTextOffset() - 1;
if (index >= 0 && text.charAt(index) == '/') {
// already seen /
return Result.CONTINUE;
}
element = parent.getPrevSibling();
} else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag) && !(element.getPrevSibling() instanceof OuterLanguageElement)) {
element = parent;
} else if (parent instanceof XmlAttributeValue) {
element = parent;
}
} else {
element = provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class);
if (element == null)
return Result.CONTINUE;
element = element.getParent();
}
if (offset > 0 && offset <= editor.getDocument().getTextLength()) {
if (editor.getDocument().getCharsSequence().charAt(offset - 1) == '/') {
// Some languages (e.g. GSP) allow character '/' in tag name.
return Result.CONTINUE;
}
}
if (element instanceof XmlAttributeValue) {
element = element.getParent().getParent();
}
while (element instanceof PsiWhiteSpace || element instanceof OuterLanguageElement) element = element.getPrevSibling();
if (element instanceof XmlDocument) {
// hack for closing tags in RHTML
element = element.getLastChild();
}
if (element == null)
return Result.CONTINUE;
if (!(element instanceof XmlTag)) {
if (element instanceof XmlTokenImpl && element.getPrevSibling() != null && element.getPrevSibling().getText().equals("<")) {
// tag is started and there is another text in the end
EditorModificationUtil.insertStringAtCaret(editor, "</" + element.getText() + ">", false, 0);
}
return Result.CONTINUE;
}
XmlTag tag = (XmlTag) element;
if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null)
return Result.CONTINUE;
if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
return Result.CONTINUE;
final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
if (startToken == null || !startToken.getText().equals("<"))
return Result.CONTINUE;
String name = tag.getName();
if (elementAtCaret instanceof XmlToken && (((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_NAME || ((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_TAG_NAME)) {
name = name.substring(0, offset - elementAtCaret.getTextOffset());
}
if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name))
return Result.CONTINUE;
if (name.isEmpty())
return Result.CONTINUE;
int tagOffset = tag.getTextRange().getStartOffset();
final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset)
return Result.CONTINUE;
HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset);
if (BraceMatchingUtil.matchBrace(editor.getDocument().getCharsSequence(), editedFile.getFileType(), iterator, true, true)) {
PsiElement parent = tag.getParent();
boolean hasBalance = true;
loop: while (parent instanceof XmlTag) {
if (name.equals(((XmlTag) parent).getName())) {
hasBalance = false;
ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode());
if (astNode == null) {
hasBalance = true;
break;
}
for (PsiElement el = parent.getNextSibling(); el != null; el = el.getNextSibling()) {
if (el instanceof PsiErrorElement && el.getText().startsWith("</" + name)) {
hasBalance = true;
break loop;
}
}
}
parent = parent.getParent();
}
if (hasBalance)
return Result.CONTINUE;
}
Collection<TextRange> cdataReformatRanges = null;
final XmlElementDescriptor descriptor = tag.getDescriptor();
EditorModificationUtil.insertStringAtCaret(editor, "</" + name + ">", false, 0);
if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent) descriptor;
cdataReformatRanges = ContainerUtil.newSmartList();
if (cDataContainer.requiresCdataBracesInContext(tag)) {
@NonNls final String cDataStart = "><![CDATA[";
final String inserted = cDataStart + "\n]]>";
EditorModificationUtil.insertStringAtCaret(editor, inserted, false, cDataStart.length());
int caretOffset = editor.getCaretModel().getOffset();
if (caretOffset >= cDataStart.length()) {
cdataReformatRanges.add(TextRange.from(caretOffset - cDataStart.length(), inserted.length() + 1));
}
}
}
if (cdataReformatRanges != null && !cdataReformatRanges.isEmpty()) {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
try {
CodeStyleManager.getInstance(project).reformatText(file, cdataReformatRanges);
} catch (IncorrectOperationException e) {
LOG.error(e);
}
}
return cdataReformatRanges != null && !cdataReformatRanges.isEmpty() ? Result.STOP : Result.CONTINUE;
}
return Result.CONTINUE;
}
use of com.intellij.psi.templateLanguages.OuterLanguageElement in project intellij-community by JetBrains.
the class XmlSlashTypedHandler method charTyped.
@Override
public Result charTyped(final char c, final Project project, @NotNull final Editor editor, @NotNull final PsiFile editedFile) {
if (!WebEditorOptions.getInstance().isAutoCloseTag())
return Result.CONTINUE;
if (c == '/' && XmlGtTypedHandler.fileContainsXmlLanguage(editedFile)) {
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (file == null)
return Result.CONTINUE;
FileViewProvider provider = file.getViewProvider();
final int offset = editor.getCaretModel().getOffset();
PsiElement element = provider.findElementAt(offset - 1, XMLLanguage.class);
if (element == null)
return Result.CONTINUE;
if (!(element.getLanguage() instanceof XMLLanguage))
return Result.CONTINUE;
ASTNode prevLeaf = element.getNode();
if (prevLeaf == null)
return Result.CONTINUE;
final String prevLeafText = prevLeaf.getText();
if ("</".equals(prevLeafText) && prevLeaf.getElementType() == XmlTokenType.XML_END_TAG_START) {
XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
if (tag != null && StringUtil.isNotEmpty(tag.getName()) && TreeUtil.findSibling(prevLeaf, XmlTokenType.XML_NAME) == null) {
// check for template language like JSP
if (provider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
PsiElement element1 = SingleRootFileViewProvider.findElementAt(file, offset - 1);
if (element1 != null) {
// case of top-level jsp tag
XmlTag tag1 = PsiTreeUtil.getParentOfType(element1, XmlTag.class);
if (shouldReplace(tag, tag1, offset)) {
tag = tag1;
} else {
// if we have enclosing jsp tag, actual tag to be completed will be previous sibling
tag1 = PsiTreeUtil.getPrevSiblingOfType(element1.getParent(), XmlTag.class);
if (shouldReplace(tag, tag1, offset)) {
tag = tag1;
}
}
}
}
EditorModificationUtil.insertStringAtCaret(editor, tag.getName() + ">", false);
autoIndent(editor);
return Result.STOP;
}
}
if (!"/".equals(prevLeafText.trim()))
return Result.CONTINUE;
while ((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE) ;
if (prevLeaf instanceof OuterLanguageElement) {
element = file.getViewProvider().findElementAt(offset - 1, file.getLanguage());
prevLeaf = element != null ? element.getNode() : null;
while ((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE) ;
}
if (prevLeaf == null)
return Result.CONTINUE;
XmlTag tag = PsiTreeUtil.getParentOfType(prevLeaf.getPsi(), XmlTag.class);
if (tag == null) {
// prevLeaf maybe in one tree and element in another
PsiElement element2 = provider.findElementAt(prevLeaf.getStartOffset(), XMLLanguage.class);
tag = PsiTreeUtil.getParentOfType(element2, XmlTag.class);
if (tag == null)
return Result.CONTINUE;
}
final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
if (startToken == null || !startToken.getText().equals("<"))
return Result.CONTINUE;
if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null)
return Result.CONTINUE;
if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
return Result.CONTINUE;
if (PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class) != null)
return Result.CONTINUE;
EditorModificationUtil.insertStringAtCaret(editor, ">", false);
return Result.STOP;
}
return Result.CONTINUE;
}
use of com.intellij.psi.templateLanguages.OuterLanguageElement in project intellij-community by JetBrains.
the class PyBaseElementImpl method findReferenceAt.
/**
* Overrides the findReferenceAt() logic in order to provide a resolve context with origin file for returned references.
* The findReferenceAt() is usually invoked from UI operations, and it helps to be able to do deeper analysis in the
* current file for such operations.
*
* @param offset the offset to find the reference at
* @return the reference or null.
*/
@Override
public PsiReference findReferenceAt(int offset) {
// copy/paste from SharedPsiElementImplUtil
PsiElement element = findElementAt(offset);
if (element == null || element instanceof OuterLanguageElement)
return null;
offset = getTextRange().getStartOffset() + offset - element.getTextRange().getStartOffset();
List<PsiReference> referencesList = new ArrayList<>();
final PsiFile file = element.getContainingFile();
final PyResolveContext resolveContext = file != null ? PyResolveContext.defaultContext().withTypeEvalContext(TypeEvalContext.codeAnalysis(file.getProject(), file)) : PyResolveContext.defaultContext();
while (element != null) {
addReferences(offset, element, referencesList, resolveContext);
offset = element.getStartOffsetInParent() + offset;
if (element instanceof PsiFile)
break;
element = element.getParent();
}
if (referencesList.isEmpty())
return null;
if (referencesList.size() == 1)
return referencesList.get(0);
return new PsiMultiReference(referencesList.toArray(new PsiReference[referencesList.size()]), referencesList.get(referencesList.size() - 1).getElement());
}
use of com.intellij.psi.templateLanguages.OuterLanguageElement in project intellij-community by JetBrains.
the class XmlBlock method splitComment.
protected List<Block> splitComment() {
if (myNode.getElementType() != XmlElementType.XML_COMMENT)
return EMPTY;
final ArrayList<Block> result = new ArrayList<>(3);
ASTNode child = myNode.getFirstChildNode();
boolean hasOuterLangElements = false;
while (child != null) {
if (child instanceof OuterLanguageElement) {
hasOuterLangElements = true;
}
result.add(new XmlBlock(child, null, null, myXmlFormattingPolicy, getChildIndent(), null, isPreserveSpace()));
child = child.getTreeNext();
}
if (hasOuterLangElements) {
return result;
} else {
return EMPTY;
}
}
Aggregations