use of org.ballerinalang.plugins.idea.psi.AnnotationAttachmentNode in project ballerina by ballerina-lang.
the class BallerinaAnnotator method annotateLeafPsiElementNodes.
private void annotateLeafPsiElementNodes(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
IElementType elementType = ((LeafPsiElement) element).getElementType();
PsiElement parentElement = element.getParent();
if (elementType == BallerinaTypes.AT && parentElement instanceof AnnotationAttachmentNode) {
Annotation annotation = holder.createInfoAnnotation(element, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.ANNOTATION);
} else if (elementType == BallerinaTypes.QUOTED_STRING) {
// In here, we annotate valid escape characters.
String text = element.getText();
Matcher matcher = VALID_ESCAPE_CHAR_PATTERN.matcher(text);
// Get the start offset of the element.
int startOffset = ((LeafPsiElement) element).getStartOffset();
// Iterate through each match.
while (matcher.find()) {
// Get the matching group.
String group = matcher.group(0);
// Calculate the start and end offsets and create the range.
TextRange range = new TextRange(startOffset + matcher.start(), startOffset + matcher.start() + group.length());
// Create the annotation.
Annotation annotation = holder.createInfoAnnotation(range, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.VALID_STRING_ESCAPE);
}
// Annotate invalid escape characters.
matcher = INVALID_ESCAPE_CHAR_PATTERN.matcher(text);
// Get the start offset of the element.
startOffset = ((LeafPsiElement) element).getStartOffset();
// Iterate through each match.
while (matcher.find()) {
// Get the matching group.
String group = matcher.group(3);
if (group != null) {
// Calculate the start and end offsets and create the range.
TextRange range = new TextRange(startOffset + matcher.start(3), startOffset + matcher.start(3) + group.length());
// Create the annotation.
Annotation annotation = holder.createInfoAnnotation(range, "Invalid string escape");
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.INVALID_STRING_ESCAPE);
}
}
AnnotationAttributeNode annotationAttributeNode = PsiTreeUtil.getParentOfType(element, AnnotationAttributeNode.class);
boolean canHighlightParameters = canHighlightParameters(element);
if (canHighlightParameters && annotationAttributeNode != null) {
// Annotate query parameters in annotation attachments.
matcher = PATH_PARAMETERS_PATTERN.matcher(text);
// Get the start offset of the element.
startOffset = ((LeafPsiElement) element).getStartOffset();
// Iterate through each match.
while (matcher.find()) {
// Get the matching value without the enclosing {}.
String value = matcher.group(2);
if (value == null) {
continue;
}
// Calculate the start and end offsets and create the range. We need to add 2 to include the
// {} ignored.
TextRange range = new TextRange(startOffset + matcher.start(1), startOffset + matcher.start(1) + value.length() + 2);
// Check whether a matching resource parameter is available.
boolean isMatchAvailable = isMatchingParamAvailable(annotationAttributeNode, value);
// Create the annotation.
if (isMatchAvailable) {
Annotation annotation = holder.createInfoAnnotation(range, "Path parameter '" + value + "'");
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.TEMPLATE_LANGUAGE_COLOR);
} else {
Annotation annotation = holder.createErrorAnnotation(range, "Path parameter '" + value + "' not found in the resource signature");
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.INVALID_STRING_ESCAPE);
}
}
}
} else if (elementType == BallerinaTypes.STRING_TEMPLATE_LITERAL_START || elementType == BallerinaTypes.XML_START) {
annotateKeyword(element, holder);
} else if (elementType == BallerinaTypes.DOCUMENTATION_TEMPLATE_START || elementType == BallerinaTypes.DEPRECATED_TEMPLATE_START) {
// This uses an overloaded method so that the color can be easily changeable if required.
annotateKeyword(element, holder, BallerinaSyntaxHighlightingColors.KEYWORD);
} else if (elementType == BallerinaTypes.STRING_TEMPLATE_EXPRESSION_START || elementType == BallerinaTypes.XML_EXPRESSION_START) {
annotateExpressionTemplateStart(element, holder);
} else if (elementType == BallerinaTypes.STRING_TEMPLATE_TEXT || elementType == BallerinaTypes.XML_TEXT) {
annotateText(element, holder);
} else if (elementType == BallerinaTypes.EXPRESSION_END) {
annotateStringLiteralTemplateEnd(element, holder);
} else if (elementType == BallerinaTypes.DOCUMENTATION_TEMPLATE_ATTRIBUTE_START) {
// Doc type.
String msg = null;
switch(element.getText().charAt(0)) {
case 'T':
msg = "Receiver";
break;
case 'P':
msg = "Parameter";
break;
case 'R':
msg = "Return Value";
break;
case 'F':
msg = "Field";
break;
case 'V':
msg = "Variable";
break;
}
TextRange textRange = element.getTextRange();
TextRange newTextRange = new TextRange(textRange.getStartOffset(), textRange.getEndOffset() - 2);
Annotation annotation = holder.createInfoAnnotation(newTextRange, msg);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.DOCUMENTATION_INLINE_CODE);
} else if (element instanceof IdentifierPSINode) {
if (parentElement.getParent() instanceof AnnotationAttachmentNode) {
Annotation annotation = holder.createInfoAnnotation(element, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.ANNOTATION);
return;
}
if (parentElement instanceof DocumentationTemplateAttributeDescriptionNode) {
Annotation annotation = holder.createInfoAnnotation(element, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.DOCUMENTATION_INLINE_CODE);
}
PsiReference reference = element.getReference();
if (reference == null || reference instanceof RecordKeyReference) {
return;
}
PsiElement resolvedElement = reference.resolve();
if (resolvedElement == null) {
return;
}
PsiElement parent = resolvedElement.getParent();
if (parent instanceof ConstantDefinitionNode) {
Annotation annotation = holder.createInfoAnnotation(element, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.CONSTANT);
} else if (parent instanceof GlobalVariableDefinitionNode) {
Annotation annotation = holder.createInfoAnnotation(element, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.GLOBAL_VARIABLE);
}
}
}
use of org.ballerinalang.plugins.idea.psi.AnnotationAttachmentNode in project ballerina by ballerina-lang.
the class BallerinaAnnotator method isMatchingParamAvailable.
private boolean isMatchingParamAvailable(@NotNull AnnotationAttributeNode annotationAttributeNode, @NotNull String value) {
ResourceDefinitionNode resourceDefinitionNode = PsiTreeUtil.getParentOfType(annotationAttributeNode, ResourceDefinitionNode.class);
if (resourceDefinitionNode == null) {
return false;
}
ParameterListNode parameterListNode = PsiTreeUtil.getChildOfType(resourceDefinitionNode, ParameterListNode.class);
if (parameterListNode == null) {
return false;
}
ParameterNode[] parameterNodes = PsiTreeUtil.getChildrenOfType(parameterListNode, ParameterNode.class);
if (parameterNodes == null) {
return false;
}
for (ParameterNode parameterNode : parameterNodes) {
AnnotationAttachmentNode annotationAttachmentNode = PsiTreeUtil.getChildOfType(parameterNode, AnnotationAttachmentNode.class);
if (annotationAttachmentNode == null) {
continue;
}
AnnotationReferenceNode annotationReferenceNode = PsiTreeUtil.getChildOfType(annotationAttachmentNode, AnnotationReferenceNode.class);
if (annotationReferenceNode == null) {
continue;
}
PsiElement paramType = annotationReferenceNode.getNameIdentifier();
if (paramType == null) {
continue;
}
if (!"PathParam".equals(paramType.getText())) {
continue;
}
Collection<AnnotationAttributeValueNode> annotationAttributeValueNodes = PsiTreeUtil.findChildrenOfType(annotationAttachmentNode, AnnotationAttributeValueNode.class);
for (AnnotationAttributeValueNode annotationAttributeValueNode : annotationAttributeValueNodes) {
SimpleLiteralNode simpleLiteralNode = PsiTreeUtil.getChildOfType(annotationAttributeValueNode, SimpleLiteralNode.class);
if (simpleLiteralNode == null || simpleLiteralNode.getFirstChild() == null) {
continue;
}
PsiElement firstChild = simpleLiteralNode.getFirstChild();
if (!(firstChild instanceof LeafPsiElement)) {
continue;
}
if (((LeafPsiElement) firstChild).getElementType() != BallerinaTypes.QUOTED_STRING) {
continue;
}
String text = firstChild.getText();
text = text.substring(1, text.length() - 1);
if (value.equals(text)) {
return true;
}
}
}
// does not have an annotation attachments.
for (ParameterNode parameterNode : parameterNodes) {
AnnotationAttachmentNode annotationAttachmentNode = PsiTreeUtil.getChildOfType(parameterNode, AnnotationAttachmentNode.class);
if (annotationAttachmentNode != null) {
continue;
}
PsiElement nameIdentifier = parameterNode.getNameIdentifier();
if (nameIdentifier == null) {
continue;
}
if (value.equals(nameIdentifier.getText())) {
return true;
}
}
return false;
}
use of org.ballerinalang.plugins.idea.psi.AnnotationAttachmentNode in project ballerina by ballerina-lang.
the class BallerinaKeywordsCompletionContributor method fillCompletionVariants.
@Override
public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
PsiElement element = parameters.getPosition();
PsiElement parent = element.getParent();
if (element instanceof LeafPsiElement) {
IElementType elementType = ((LeafPsiElement) element).getElementType();
if (elementType == BallerinaTypes.FLOATING_POINT) {
return;
}
}
if (parent instanceof NameReferenceNode) {
PsiElement prevVisibleLeaf = PsiTreeUtil.prevVisibleLeaf(element);
if (prevVisibleLeaf != null && "public".equals(prevVisibleLeaf.getText())) {
result.addAllElements(getFileLevelKeywordsAsLookups(false, true, true));
}
if (prevVisibleLeaf instanceof IdentifierPSINode) {
result.addElement(getAttachKeyword());
return;
}
ANTLRPsiNode definitionParent = PsiTreeUtil.getParentOfType(parent, CallableUnitBodyNode.class, ServiceBodyNode.class, ConnectorBodyNode.class);
if (definitionParent != null && prevVisibleLeaf != null && "=".equals(prevVisibleLeaf.getText())) {
result.addElement(getCreateKeyword());
result.addElement(getTypeOfKeyword());
result.addElement(getLengthOfKeyword());
result.addAllElements(getValueKeywords());
}
ExpressionNode expressionNode = PsiTreeUtil.getParentOfType(parent, ExpressionNode.class);
if (expressionNode != null && expressionNode.getChildren().length == 1) {
PsiReference referenceAt = parent.findReferenceAt(0);
if (referenceAt == null || referenceAt instanceof NameReference) {
result.addAllElements(getValueKeywords());
}
PsiElement nextVisibleLeaf = PsiTreeUtil.nextVisibleLeaf(element);
if ((prevVisibleLeaf != null && "(".equals(prevVisibleLeaf.getText())) || (nextVisibleLeaf != null && ")".equals(nextVisibleLeaf.getText()) && !":".equals(prevVisibleLeaf.getText()))) {
addOtherTypeAsLookup(result);
addValueTypesAsLookups(result);
addReferenceTypesAsLookups(result);
}
}
AnnotationAttachmentNode attachmentNode = PsiTreeUtil.getParentOfType(parent, AnnotationAttachmentNode.class);
if (attachmentNode != null) {
result.addAllElements(getValueKeywords());
}
TypeNameNode typeNameNode = PsiTreeUtil.getParentOfType(parent, TypeNameNode.class);
if (typeNameNode != null && prevVisibleLeaf != null && !prevVisibleLeaf.getText().matches("[:.=]")) {
AnnotationDefinitionNode annotationDefinitionNode = PsiTreeUtil.getParentOfType(typeNameNode, AnnotationDefinitionNode.class);
if (annotationDefinitionNode == null) {
addOtherTypeAsLookup(result);
addXmlnsAsLookup(result);
addValueTypesAsLookups(result);
addReferenceTypesAsLookups(result);
}
}
}
if (parent instanceof StatementNode) {
PsiElement prevVisibleSibling = PsiTreeUtil.prevVisibleLeaf(element);
if (prevVisibleSibling != null && "=".equals(prevVisibleSibling.getText())) {
result.addElement(getCreateKeyword());
result.addElement(getTypeOfKeyword());
result.addElement(getLengthOfKeyword());
}
}
if (parent instanceof ConstantDefinitionNode || parent instanceof PsiErrorElement) {
PsiElement prevVisibleSibling = PsiTreeUtil.prevVisibleLeaf(element);
if (prevVisibleSibling != null && "const".equals(prevVisibleSibling.getText())) {
addValueTypesAsLookups(result);
return;
}
}
if (parent instanceof PsiErrorElement) {
PsiElement prevVisibleSibling = PsiTreeUtil.prevVisibleLeaf(element);
PsiElement definitionNode = PsiTreeUtil.getParentOfType(element, FunctionDefinitionNode.class, ServiceDefinitionNode.class, ConnectorDefinitionNode.class, ResourceDefinitionNode.class);
if (definitionNode != null) {
if (prevVisibleSibling != null && "=".equals(prevVisibleSibling.getText())) {
result.addElement(getCreateKeyword());
result.addAllElements(getValueKeywords());
result.addElement(getTypeOfKeyword());
result.addElement(getLengthOfKeyword());
}
if (prevVisibleSibling != null && prevVisibleSibling.getText().matches("[;{}]") && !(prevVisibleSibling.getParent() instanceof AnnotationAttachmentNode)) {
// Todo - change method
addOtherTypeAsLookup(result);
addXmlnsAsLookup(result);
addValueTypesAsLookups(result);
addReferenceTypesAsLookups(result);
if (definitionNode instanceof FunctionDefinitionNode) {
result.addAllElements(getFunctionSpecificKeywords());
}
if (definitionNode instanceof ResourceDefinitionNode) {
result.addAllElements(getResourceSpecificKeywords());
}
if (definitionNode instanceof ServiceDefinitionNode) {
result.addAllElements(getServiceSpecificKeywords());
}
if (definitionNode instanceof ConnectorDefinitionNode) {
result.addAllElements(getConnectorSpecificKeywords());
}
if (!(definitionNode instanceof ServiceDefinitionNode || definitionNode instanceof ConnectorDefinitionNode)) {
result.addAllElements(getCommonKeywords());
}
}
if (prevVisibleSibling != null && !prevVisibleSibling.getText().matches("[{}]")) /*|| !(prevVisibleSibling.getParent() instanceof AnnotationAttachmentNode)*/
{
result.addAllElements(getValueKeywords());
}
}
ConnectorBodyNode connectorBodyNode = PsiTreeUtil.getParentOfType(element, ConnectorBodyNode.class);
if (connectorBodyNode != null) {
result.addAllElements(getConnectorSpecificKeywords());
}
ConnectorDefinitionNode connectorDefinitionNode = PsiTreeUtil.getParentOfType(element, ConnectorDefinitionNode.class);
if (connectorDefinitionNode != null) {
result.addAllElements(getConnectorSpecificKeywords());
}
return;
}
if (parent instanceof NameReferenceNode) {
RecordKeyValueNode recordKeyValueNode = PsiTreeUtil.getParentOfType(parent, RecordKeyValueNode.class);
if (recordKeyValueNode == null) {
PsiElement prevVisibleSibling = PsiTreeUtil.prevVisibleLeaf(element);
if (prevVisibleSibling != null && "{".equals(prevVisibleSibling.getText())) {
FunctionDefinitionNode functionDefinitionNode = PsiTreeUtil.getParentOfType(element, FunctionDefinitionNode.class);
if (functionDefinitionNode != null) {
// Todo - change method
addOtherTypeAsLookup(result);
addXmlnsAsLookup(result);
addValueTypesAsLookups(result);
addReferenceTypesAsLookups(result);
result.addAllElements(getFunctionSpecificKeywords());
result.addAllElements(getCommonKeywords());
result.addAllElements(getValueKeywords());
}
ServiceBodyNode serviceBodyNode = PsiTreeUtil.getParentOfType(element, ServiceBodyNode.class);
if (serviceBodyNode != null) {
result.addAllElements(getServiceSpecificKeywords());
}
ConnectorBodyNode connectorBodyNode = PsiTreeUtil.getParentOfType(element, ConnectorBodyNode.class);
if (connectorBodyNode != null) {
result.addAllElements(getConnectorSpecificKeywords());
}
} else if (prevVisibleSibling != null && "}".equals(prevVisibleSibling.getText())) {
result.addAllElements(getFileLevelKeywordsAsLookups(true, false, false));
}
}
}
if (parent instanceof ResourceDefinitionNode) {
result.addAllElements(getServiceSpecificKeywords());
}
if (parent.getPrevSibling() == null) {
GlobalVariableDefinitionNode globalVariableDefinitionNode = PsiTreeUtil.getParentOfType(element, GlobalVariableDefinitionNode.class);
if (globalVariableDefinitionNode != null) {
PsiElement prevVisibleSibling = PsiTreeUtil.prevVisibleLeaf(element);
if (prevVisibleSibling != null && !(";".equals(prevVisibleSibling.getText()))) {
if (!(prevVisibleSibling.getText().matches("[:=]") || prevVisibleSibling instanceof IdentifierPSINode || "create".equals(prevVisibleSibling.getText()))) {
if (prevVisibleSibling instanceof LeafPsiElement) {
IElementType elementType = ((LeafPsiElement) prevVisibleSibling).getElementType();
if (BallerinaParserDefinition.KEYWORDS.contains(elementType)) {
return;
}
}
result.addAllElements(getCommonKeywords());
}
return;
}
PsiElement definitionNode = globalVariableDefinitionNode.getParent();
PackageDeclarationNode prevPackageDeclarationNode = PsiTreeUtil.getPrevSiblingOfType(definitionNode, PackageDeclarationNode.class);
ImportDeclarationNode prevImportDeclarationNode = PsiTreeUtil.getPrevSiblingOfType(definitionNode, ImportDeclarationNode.class);
ConstantDefinitionNode prevConstantDefinitionNode = PsiTreeUtil.getPrevSiblingOfType(definitionNode, ConstantDefinitionNode.class);
DefinitionNode prevDefinitionNode = PsiTreeUtil.getPrevSiblingOfType(definitionNode, DefinitionNode.class);
GlobalVariableDefinitionNode prevGlobalVariableDefinition = PsiTreeUtil.findChildOfType(prevDefinitionNode, GlobalVariableDefinitionNode.class);
if (prevPackageDeclarationNode == null && prevImportDeclarationNode == null && prevConstantDefinitionNode == null && prevGlobalVariableDefinition == null) {
result.addAllElements(getFileLevelKeywordsAsLookups(true, true, true));
} else if ((prevPackageDeclarationNode != null || prevImportDeclarationNode != null) && prevConstantDefinitionNode == null && prevGlobalVariableDefinition == null) {
result.addAllElements(getFileLevelKeywordsAsLookups(true, false, true));
} else {
result.addAllElements(getFileLevelKeywordsAsLookups(true, false, false));
}
addTypeNamesAsLookups(result);
}
}
if (element instanceof IdentifierPSINode) {
PsiReference reference = element.findReferenceAt(element.getTextLength());
if (reference instanceof WorkerReference) {
result.addAllElements(getWorkerInteractionKeywords());
}
}
}
use of org.ballerinalang.plugins.idea.psi.AnnotationAttachmentNode in project ballerina by ballerina-lang.
the class BallerinaAnnotator method annotatePackageNameNodes.
private void annotatePackageNameNodes(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
PsiElement parent = element.getParent();
if (parent != null) {
PsiElement superParent = parent.getParent();
if (superParent != null && superParent instanceof AnnotationAttachmentNode) {
Annotation annotation = holder.createInfoAnnotation(element, null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.ANNOTATION);
return;
}
}
ImportDeclarationNode importDeclarationNode = PsiTreeUtil.getParentOfType(element, ImportDeclarationNode.class);
if (importDeclarationNode != null) {
return;
}
PackageDeclarationNode packageDeclarationNode = PsiTreeUtil.getParentOfType(element, PackageDeclarationNode.class);
if (packageDeclarationNode != null) {
return;
}
AnnotationAttachmentNode annotationAttachmentNode = PsiTreeUtil.getParentOfType(element, AnnotationAttachmentNode.class);
if (annotationAttachmentNode != null) {
return;
}
XmlAttribNode xmlAttribNode = PsiTreeUtil.getParentOfType(element, XmlAttribNode.class);
if (xmlAttribNode != null) {
return;
}
// Create the annotation.
Annotation annotation = holder.createInfoAnnotation(element.getTextRange(), null);
annotation.setTextAttributes(BallerinaSyntaxHighlightingColors.PACKAGE);
}
use of org.ballerinalang.plugins.idea.psi.AnnotationAttachmentNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method getAttachmentType.
/**
* Returns the attachment type by checking the nodes.
*
* @param identifier identifier node of the annotation attachment node
* @return attachment type.
*/
@Nullable
public static String getAttachmentType(@NotNull IdentifierPSINode identifier) {
PsiElement parent = identifier.getParent();
PsiElement superParent = parent.getParent();
PsiElement nextSibling = PsiTreeUtil.skipSiblingsForward(superParent, PsiWhiteSpace.class, PsiComment.class, AnnotationAttachmentNode.class);
String type = null;
if (nextSibling == null) {
AnnotationAttachmentNode annotationAttachmentNode = PsiTreeUtil.getParentOfType(identifier, AnnotationAttachmentNode.class);
if (annotationAttachmentNode != null) {
PsiElement definitionNode = annotationAttachmentNode.getParent();
type = getAnnotationAttachmentType(definitionNode);
}
} else if (nextSibling instanceof DefinitionNode) {
PsiElement[] children = nextSibling.getChildren();
if (children.length != 0) {
PsiElement definitionNode = children[0];
type = getAnnotationAttachmentType(definitionNode);
}
} else if (nextSibling.getParent() instanceof ResourceDefinitionNode) {
type = "resource";
} else if (nextSibling instanceof ActionDefinitionNode || nextSibling.getParent() instanceof ActionDefinitionNode || parent instanceof ActionDefinitionNode) {
type = "action";
} else if (nextSibling.getParent() instanceof ParameterNode) {
type = "parameter";
}
return type;
}
Aggregations