use of com.intellij.lang.ASTNode in project intellij-community by JetBrains.
the class XsltIntroduceVariableAction method extractImpl.
protected boolean extractImpl(XPathExpression expression, Set<XPathExpression> matchingExpressions, List<XmlTag> otherMatches, IntroduceVariableOptions dlg) {
final XmlAttribute attribute = PsiTreeUtil.getContextOfType(expression, XmlAttribute.class, true);
assert attribute != null;
try {
final String name = dlg.getName();
final XmlTag insertionPoint = XsltCodeInsightUtil.findVariableInsertionPoint(attribute.getParent(), XsltCodeInsightUtil.getUsageBlock(expression), name, dlg.isReplaceAll() ? otherMatches.toArray(new XmlTag[otherMatches.size()]) : XmlTag.EMPTY);
final XmlTag parentTag = insertionPoint.getParentTag();
assert parentTag != null : "Could not locate position to create variable at";
final XmlTag xmlTag = parentTag.createChildTag("variable", XsltSupport.XSLT_NS, null, false);
xmlTag.setAttribute("name", name);
xmlTag.setAttribute("select", expression.getText());
// TODO: revisit the formatting
final PsiElement element = parentTag.addBefore(xmlTag, insertionPoint);
final ASTNode node1 = parentTag.getNode();
assert node1 != null;
final ASTNode node2 = element.getNode();
assert node2 != null;
CodeStyleManager.getInstance(xmlTag.getManager().getProject()).reformatNewlyAddedElement(node1, node2);
final XPathVariableReference var = XPathChangeUtil.createVariableReference(expression, name);
expression.replace(var);
if (dlg.isReplaceAll()) {
for (XPathExpression expr : matchingExpressions) {
expr.replace(XPathChangeUtil.createVariableReference(expr, name));
}
return false;
} else {
return true;
}
} catch (IncorrectOperationException e) {
Logger.getInstance(getClass().getName()).error(e);
return false;
}
}
use of com.intellij.lang.ASTNode in project intellij-community by JetBrains.
the class XsltExtractFunctionAction method extractImpl.
protected boolean extractImpl(XPathExpression expression, Set<XPathExpression> matchingExpressions, List<XmlTag> otherMatches, RefactoringOptions dlg) {
final XmlAttribute attribute = PsiTreeUtil.getContextOfType(expression, XmlAttribute.class, true);
assert attribute != null;
try {
final String name = dlg.getName();
final XmlTag rootTag = ((XmlFile) attribute.getParent().getContainingFile()).getRootTag();
final XmlTag[] templates = rootTag.findSubTags("template", XsltSupport.XSLT_NS);
final XmlTag insertionPoint = templates.length > 0 ? templates[0] : rootTag.getSubTags()[0];
final XmlTag parentTag = insertionPoint.getParentTag();
assert parentTag != null : "Could not locate position to create function at";
final XmlTag xmlTag = parentTag.createChildTag("function", XsltSupport.XSLT_NS, null, false);
xmlTag.setAttribute("name", name);
final XPathType type = ExpectedTypeUtil.mapType(expression, expression.getType());
xmlTag.setAttribute("as", prefixedName(type, insertionPoint));
final StringBuilder argList = new StringBuilder();
final List<XPathVariableReference> references = RefactoringUtil.collectVariableReferences(expression);
for (XPathVariableReference reference : references) {
final XPathVariable variable = reference.resolve();
if (variable instanceof XsltVariable) {
// don't pass through global parameters and variables
if (XsltCodeInsightUtil.getTemplateTag(variable, false) != null) {
final XmlTag param = parentTag.createChildTag("param", XsltSupport.XSLT_NS, null, false);
param.setAttribute("name", variable.getName());
if (!variable.getType().isAbstract()) {
param.setAttribute("as", prefixedName(ExpectedTypeUtil.mapType(expression, variable.getType()), parentTag));
}
RefactoringUtil.addParameter(xmlTag, param);
if (argList.length() > 0) {
argList.append(", ");
}
argList.append("$").append(variable.getName());
}
}
}
final XmlTag seqTag = parentTag.createChildTag("sequence", XsltSupport.XSLT_NS, null, false);
seqTag.setAttribute("select", expression.getText());
xmlTag.add(seqTag);
// TODO: revisit the formatting
final PsiElement element = parentTag.addBefore(xmlTag, insertionPoint);
final ASTNode node1 = parentTag.getNode();
assert node1 != null;
final ASTNode node2 = element.getNode();
assert node2 != null;
CodeStyleManager.getInstance(xmlTag.getManager().getProject()).reformatNewlyAddedElement(node1, node2);
final XPathExpression var = XPathChangeUtil.createExpression(expression, name + "(" + argList + ")");
expression.replace(var);
return true;
} catch (IncorrectOperationException e) {
Logger.getInstance(getClass().getName()).error(e);
return false;
}
}
use of com.intellij.lang.ASTNode in project intellij-community by JetBrains.
the class XPathLanguageInjector method getLanguagesToInject.
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
final XmlAttribute attribute = (XmlAttribute) context;
if (!XsltSupport.isXPathAttribute(attribute))
return;
XmlAttributeValueImpl value = (XmlAttributeValueImpl) attribute.getValueElement();
if (value == null)
return;
ASTNode type = value.findChildByType(XmlElementType.XML_ENTITY_REF);
// workaround for inability to inject into text with entity refs (e.g. IDEA-72972) TODO: fix it
if (type != null)
return;
final XsltChecker.LanguageLevel languageLevel = XsltSupport.getXsltLanguageLevel(attribute.getContainingFile());
final TextRange[] ranges = getInjectionRanges(attribute, languageLevel);
for (TextRange range : ranges) {
// workaround for http://www.jetbrains.net/jira/browse/IDEA-10096
TextRange rangeInsideHost;
String prefix;
if (range instanceof AVTRange) {
if (((AVTRange) range).myComplete) {
rangeInsideHost = range.shiftRight(2).grown(-2);
prefix = "";
} else {
// we need to keep the "'}' expected" parse error
rangeInsideHost = range.shiftRight(2).grown(-1);
prefix = "{";
}
} else {
rangeInsideHost = range;
prefix = "";
}
if (value.getTextRange().contains(rangeInsideHost.shiftRight(value.getTextRange().getStartOffset()))) {
registrar.startInjecting(languageLevel.getXPathVersion().getLanguage()).addPlace(prefix, "", value, rangeInsideHost).doneInjecting();
}
}
}
use of com.intellij.lang.ASTNode in project intellij-community by JetBrains.
the class ReplaceWithXslAttribute method isAvailable.
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!XsltSupport.isXsltFile(file))
return false;
final int offset = editor.getCaretModel().getOffset();
final PsiElement element = file.findElementAt(offset);
final XmlAttribute attr = PsiTreeUtil.getParentOfType(element, XmlAttribute.class, false);
if (attr == null || attr.getValueElement() == null) {
return false;
}
if (XsltSupport.isXsltTag(attr.getParent())) {
return false;
}
final ASTNode node = attr.getNode();
if (node == null)
return false;
final ASTNode nameNode = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node);
if (nameNode == null) {
return false;
} else {
return nameNode.getTextRange().contains(offset);
}
}
use of com.intellij.lang.ASTNode in project intellij-community by JetBrains.
the class XPathAnnotator method checkFunctionCall.
private static void checkFunctionCall(AnnotationHolder holder, XPathFunctionCall call, @NotNull ContextProvider contextProvider) {
final ASTNode node = call.getNode().findChildByType(XPathTokenTypes.FUNCTION_NAME);
if (node == null) {
return;
}
final QName name = contextProvider.getQName(call);
final XPathFunction function = call.resolve();
final Function functionDecl = function != null ? function.getDeclaration() : null;
if (functionDecl == null) {
final PrefixedNameImpl qName = (PrefixedNameImpl) call.getQName();
// need special check for extension functions
if (call.getQName().getPrefix() != null && contextProvider.getFunctionContext().allowsExtensions()) {
final PsiReference[] references = call.getReferences();
if (references.length > 1 && references[1].resolve() == null) {
final Annotation ann = holder.createErrorAnnotation(qName.getPrefixNode(), "Extension namespace prefix '" + qName.getPrefix() + "' has not been declared");
ann.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
} else if (name != null) {
final String extNS = name.getNamespaceURI();
if (!StringUtil.isEmpty(extNS)) {
final Set<Pair<QName, Integer>> pairs = contextProvider.getFunctionContext().getFunctions().keySet();
for (Pair<QName, Integer> pair : pairs) {
// extension namespace is known
final String uri = pair.first.getNamespaceURI();
if (uri != null && uri.equals(extNS)) {
holder.createWarningAnnotation(node, "Unknown function '" + name + "'");
}
}
}
}
} else {
if (name != null) {
holder.createWarningAnnotation(node, "Unknown function '" + name + "'");
} else if (qName.getPrefixNode() != null) {
final Annotation ann = holder.createErrorAnnotation(qName.getPrefixNode(), "Extension namespace prefix '" + qName.getPrefix() + "' has not been declared");
ann.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
} else {
final XPathExpression[] arguments = call.getArgumentList();
for (int i = 0; i < arguments.length; i++) {
checkArgument(holder, arguments[i], i, functionDecl.getParameters());
}
if (arguments.length < functionDecl.getMinArity()) {
if (functionDecl.getMinArity() == 1) {
holder.createErrorAnnotation(node, "Missing argument for function '" + name + "'");
} else {
final Parameter last = functionDecl.getParameters()[functionDecl.getParameters().length - 1];
final String atLeast = last.kind == Parameter.Kind.OPTIONAL || last.kind == Parameter.Kind.VARARG ? "at least " : "";
holder.createErrorAnnotation(node, "Function '" + name + "' requires " + atLeast + functionDecl.getMinArity() + " arguments");
}
}
}
}
Aggregations