use of org.ballerinalang.plugins.idea.psi.PackageDeclarationNode 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.PackageDeclarationNode in project ballerina by ballerina-lang.
the class BallerinaExternalAnnotator method getPackageName.
/**
* Return the package name correspond to the provided file. This method will also consider the directory structure
* as well. If the directory structure is different than the declared package in the file, relative directory
* structure will be converted to package name and will be returned. Following 2 scenarios need to be considered.
* <p>
* Scenario 1 - Incorrect package declared in file. Correct directory structure.
* Scenario 2 - Package declared in files in project root.
*
* @param file a psi file
* @return package name correspond to the provided file
*/
private String getPackageName(PsiFile file) {
// Get the package name specified in the file.
PackageDeclarationNode packageDeclarationNode = PsiTreeUtil.findChildOfType(file, PackageDeclarationNode.class);
if (packageDeclarationNode == null) {
return null;
}
FullyQualifiedPackageNameNode packageNameNode = PsiTreeUtil.getChildOfType(packageDeclarationNode, FullyQualifiedPackageNameNode.class);
if (packageNameNode == null) {
return null;
}
String packageNameInFile = packageNameNode.getText();
// Get the parent directory.
PsiDirectory psiDirectory = file.getParent();
if (psiDirectory == null) {
return packageNameInFile;
}
// Package declaration might have an incorrect package declaration. So need to validate against directory name.
if (packageNameInFile.endsWith(psiDirectory.getName())) {
return packageNameInFile;
}
// Get the current module.
Module module = ModuleUtilCore.findModuleForPsiElement(file);
// Calculate the source root. This is used to get the relative directory path.
String sourceRoot = file.getProject().getBasePath();
if (module != null && FileUtil.exists(module.getModuleFilePath())) {
sourceRoot = StringUtil.trimEnd(PathUtil.getParentPath(module.getModuleFilePath()), BallerinaConstants.IDEA_CONFIG_DIRECTORY);
}
// Get the package according to the directory structure.
String directoryPath = psiDirectory.getVirtualFile().getPath();
if (sourceRoot == null) {
return packageNameInFile;
}
String packageName = directoryPath.replace(sourceRoot, "").replaceAll("[/\\\\]", "\\.");
// If the package name is empty, that means the file is in the project root.
if (packageName.isEmpty()) {
return null;
}
// Otherwise return the calculated package path.
return packageName;
}
use of org.ballerinalang.plugins.idea.psi.PackageDeclarationNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method addImport.
/**
* Adds an import declaration node to the file.
*
* @param file file which is to be used to insert the import declaration node
* @param importPath import path to be used in the import declaration node
* @param alias alias if needed. If this is {@code null}, it will be ignored
* @return import declaration node which is added
*/
@NotNull
public static ImportDeclarationNode addImport(@NotNull PsiFile file, @NotNull String importPath, @Nullable String alias) {
PsiElement addedNode;
Collection<ImportDeclarationNode> importDeclarationNodes = PsiTreeUtil.findChildrenOfType(file, ImportDeclarationNode.class);
Project project = file.getProject();
ImportDeclarationNode importDeclaration = BallerinaElementFactory.createImportDeclaration(project, importPath, alias);
if (importDeclarationNodes.isEmpty()) {
Collection<PackageDeclarationNode> packageDeclarationNodes = PsiTreeUtil.findChildrenOfType(file, PackageDeclarationNode.class);
if (packageDeclarationNodes.isEmpty()) {
PsiElement[] children = file.getChildren();
// Children cannot be empty since the IDEA adds placeholder string
PsiElement nonEmptyElement = PsiTreeUtil.skipSiblingsForward(children[0], PsiWhiteSpace.class, PsiComment.class);
if (nonEmptyElement == null) {
nonEmptyElement = children[0];
}
addedNode = file.addBefore(importDeclaration, children[0]);
file.addBefore(BallerinaElementFactory.createDoubleNewLine(project), nonEmptyElement);
} else {
PackageDeclarationNode packageDeclarationNode = packageDeclarationNodes.iterator().next();
PsiElement parent = packageDeclarationNode.getParent();
addedNode = parent.addAfter(importDeclaration, packageDeclarationNode);
parent.addAfter(BallerinaElementFactory.createDoubleNewLine(project), packageDeclarationNode);
}
} else {
LinkedList<ImportDeclarationNode> importDeclarations = new LinkedList<>(importDeclarationNodes);
ImportDeclarationNode lastImport = importDeclarations.getLast();
addedNode = lastImport.getParent().addAfter(importDeclaration, lastImport);
lastImport.getParent().addAfter(BallerinaElementFactory.createNewLine(project), lastImport);
}
return ((ImportDeclarationNode) addedNode);
}
use of org.ballerinalang.plugins.idea.psi.PackageDeclarationNode in project ballerina by ballerina-lang.
the class PackageNameReference method multiResolve.
@NotNull
@Override
public ResolveResult[] multiResolve(boolean incompleteCode) {
IdentifierPSINode identifier = getElement();
if (identifier == null) {
return new ResolveResult[0];
}
AliasNode aliasNode = PsiTreeUtil.getParentOfType(identifier, AliasNode.class);
if (aliasNode != null) {
return new ResolveResult[0];
}
List<ResolveResult> results = new ArrayList<>();
ImportDeclarationNode importDeclarationNode = PsiTreeUtil.getParentOfType(identifier, ImportDeclarationNode.class);
if (importDeclarationNode != null) {
List<PsiDirectory> directories = BallerinaPsiImplUtil.resolveDirectory(identifier);
for (PsiDirectory directory : directories) {
results.add(new PsiElementResolveResult(directory));
}
// Return the results.
return results.toArray(new ResolveResult[results.size()]);
}
PackageDeclarationNode packageDeclarationNode = PsiTreeUtil.getParentOfType(identifier, PackageDeclarationNode.class);
if (packageDeclarationNode != null) {
// If this is a package declaration, resolve the directory.
List<PsiDirectory> directories = BallerinaPsiImplUtil.resolveDirectory(identifier);
for (PsiDirectory directory : directories) {
results.add(new PsiElementResolveResult(directory));
}
// Return the results.
return results.toArray(new ResolveResult[results.size()]);
}
PsiFile containingFile = identifier.getContainingFile();
if (containingFile == null) {
return new ResolveResult[0];
}
List<PsiElement> importedPackages = BallerinaPsiImplUtil.getImportedPackagesInCurrentFile(containingFile);
for (PsiElement importedPackage : importedPackages) {
String packageName = importedPackage.getText();
if (packageName == null || packageName.isEmpty()) {
continue;
}
if (packageName.equals(identifier.getText())) {
PsiReference reference = importedPackage.findReferenceAt(0);
if (reference != null) {
PsiElement resolvedElement = reference.resolve();
if (resolvedElement != null) {
results.add(new PsiElementResolveResult(resolvedElement));
}
}
}
}
importedPackages = BallerinaPsiImplUtil.getPackagesImportedAsAliasInCurrentFile(containingFile);
for (PsiElement importedPackage : importedPackages) {
String packageName = importedPackage.getText();
if (packageName == null || packageName.isEmpty()) {
continue;
}
if (packageName.equals(identifier.getText())) {
IdentifierPSINode nameNode = PsiTreeUtil.findChildOfType(importedPackage, IdentifierPSINode.class);
if (nameNode != null) {
results.add(new PsiElementResolveResult(nameNode));
}
}
}
return results.toArray(new ResolveResult[results.size()]);
}
use of org.ballerinalang.plugins.idea.psi.PackageDeclarationNode in project ballerina by ballerina-lang.
the class BallerinaImportOptimizer method getUsedImportDeclarations.
/**
* Used to get used imports in a file.
*
* @param file a {@link PsiFile} element
* @return list of used {@link ImportDeclarationNode} in the file.
*/
private List<ImportDeclarationNode> getUsedImportDeclarations(@NotNull PsiFile file) {
// This is used to track all packages used in the file.
List<String> usedPackages = new LinkedList<>();
Collection<PackageNameNode> packageNameNodes = PsiTreeUtil.findChildrenOfType(file, PackageNameNode.class);
for (PackageNameNode packageNameNode : packageNameNodes) {
ProgressManager.checkCanceled();
if (packageNameNode == null) {
continue;
}
PackageDeclarationNode packageDeclarationNode = PsiTreeUtil.getParentOfType(packageNameNode, PackageDeclarationNode.class);
if (packageDeclarationNode != null) {
continue;
}
ImportDeclarationNode importDeclarationNode = PsiTreeUtil.getParentOfType(packageNameNode, ImportDeclarationNode.class);
if (importDeclarationNode != null) {
continue;
}
XmlAttribNode xmlAttribNode = PsiTreeUtil.getParentOfType(packageNameNode, XmlAttribNode.class);
if (xmlAttribNode != null) {
continue;
}
PsiElement nameIdentifier = packageNameNode.getNameIdentifier();
if (nameIdentifier == null) {
continue;
}
usedPackages.add(nameIdentifier.getText());
}
List<ImportDeclarationNode> usedImportDeclarations = new LinkedList<>();
List<String> fullyQualifiedImportedPackages = new LinkedList<>();
List<String> importedPackages = new LinkedList<>();
Collection<ImportDeclarationNode> importDeclarationNodes = PsiTreeUtil.findChildrenOfType(file, ImportDeclarationNode.class);
for (ImportDeclarationNode importDeclarationNode : importDeclarationNodes) {
ProgressManager.checkCanceled();
if (importDeclarationNode == null) {
continue;
}
// Check unused imports. No need to check for fully qualified path since we cant import packages of same
// name.
List<PackageNameNode> packageNames = new ArrayList<>(PsiTreeUtil.findChildrenOfType(importDeclarationNode, PackageNameNode.class));
PackageNameNode lastPackage = ContainerUtil.getLastItem(packageNames);
if (lastPackage == null) {
continue;
}
String lastPackageName = lastPackage.getText();
if (!usedPackages.contains(lastPackageName)) {
continue;
}
// Check conflicting imports (which ends with same package name).
if (importedPackages.contains(lastPackageName)) {
continue;
}
importedPackages.add(lastPackageName);
// Check redeclared imports.
FullyQualifiedPackageNameNode fullyQualifiedPackageName = PsiTreeUtil.getChildOfType(importDeclarationNode, FullyQualifiedPackageNameNode.class);
if (fullyQualifiedPackageName == null) {
continue;
}
if (fullyQualifiedImportedPackages.contains(fullyQualifiedPackageName.getText())) {
continue;
}
fullyQualifiedImportedPackages.add(fullyQualifiedPackageName.getText());
usedImportDeclarations.add(importDeclarationNode);
}
return usedImportDeclarations;
}
Aggregations