use of com.perl5.lang.perl.psi.PerlSubDefinitionElement in project Perl5-IDEA by Camelcade.
the class PerlBraceMatcher method getCodeConstructStart.
@Override
public int getCodeConstructStart(PsiFile file, int openingBraceOffset) {
PsiElement element = file.findElementAt(openingBraceOffset);
if (element == null || element instanceof PsiFile) {
return openingBraceOffset;
}
PsiElement codeBlock = element.getParent();
if (codeBlock != null && codeBlock instanceof PsiPerlBlock) {
PsiElement blockContainer = codeBlock.getParent();
if (blockContainer != null) {
if (blockContainer instanceof PerlSubDefinitionElement || blockContainer instanceof PsiPerlForCompound) {
return blockContainer.getTextOffset();
} else if (blockContainer instanceof PsiPerlConditionalBlock || blockContainer instanceof PsiPerlIfCompoundImpl) {
PsiElement keyword = blockContainer.getPrevSibling();
while (keyword != null && (keyword instanceof PsiWhiteSpace || keyword instanceof PsiComment)) {
keyword = keyword.getPrevSibling();
}
if (keyword != null) {
return keyword.getTextOffset();
}
}
}
}
return openingBraceOffset;
}
use of com.perl5.lang.perl.psi.PerlSubDefinitionElement in project Perl5-IDEA by Camelcade.
the class PerlMooseInnerReference method resolveInner.
@NotNull
@Override
protected ResolveResult[] resolveInner(boolean incompleteCode) {
List<ResolveResult> result = new ArrayList<>();
PsiElement element = getElement();
String subName = null;
PerlSubDefinitionElement subDefinitionBase = PsiTreeUtil.getParentOfType(element, PerlSubDefinitionElement.class);
if (subDefinitionBase != null) {
subName = subDefinitionBase.getSubName();
}
PerlMooseAugmentStatement augmentStatement = PsiTreeUtil.getParentOfType(element, PerlMooseAugmentStatement.class);
if (augmentStatement != null) {
subName = augmentStatement.getSubName();
}
if (subName != null) {
PerlNamespaceDefinitionElement namespaceDefinition = PsiTreeUtil.getParentOfType(element, PerlNamespaceDefinitionElement.class);
Set<PerlNamespaceDefinitionElement> recursionSet = new THashSet<>();
if (StringUtil.isNotEmpty(subName) && namespaceDefinition != null) {
collectNamespaceMethodsAugmentations(namespaceDefinition, subName, recursionSet, result);
}
}
return result.toArray(new ResolveResult[result.size()]);
}
use of com.perl5.lang.perl.psi.PerlSubDefinitionElement in project Perl5-IDEA by Camelcade.
the class PerlLoopControlInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
PerlSubDefinitionElement breakDefinition = PerlBuiltInSubsService.getInstance(holder.getProject()).findSub("break");
return new PerlVisitor() {
@Override
public void visitNextExpr(@NotNull PsiPerlNextExpr o) {
processLoopsControl(o);
}
@Override
public void visitRedoExpr(@NotNull PsiPerlRedoExpr o) {
processLoopsControl(o);
}
@Override
public void visitLastExpr(@NotNull PsiPerlLastExpr o) {
processLoopsControl(o);
}
@Override
public void visitContinueExpr(@NotNull PsiPerlContinueExpr o) {
PsiElement position = o;
boolean isInsideTheLoop = false;
while (true) {
PsiElement closestBlockContainer = getClosestBlockContainer(position);
if (closestBlockContainer == null) {
break;
}
IElementType blockContainerElementType = PsiUtilCore.getElementType(closestBlockContainer);
if (blockContainerElementType == WHEN_COMPOUND || blockContainerElementType == DEFAULT_COMPOUND) {
return;
} else if (LOOPS_CONTAINERS.contains(blockContainerElementType)) {
isInsideTheLoop = true;
} else if (blockContainerElementType == NAMED_BLOCK) {
break;
} else if (MAP_GREP.contains(blockContainerElementType)) {
break;
} else if (BLOCKS_WITH_RETURN_VALUE.contains(blockContainerElementType)) {
break;
} else if (blockContainerElementType == GIVEN_COMPOUND) {
break;
}
position = closestBlockContainer;
}
if (isInsideTheLoop) {
holder.registerProblem(o, PerlBundle.message("perl.inspection.loop.control.continue.instead.of.next"), new ReplaceWithExpressionQuickFix("next"));
} else {
problem(o, "perl.inspection.loop.control.continue");
}
}
@Override
public void visitSubNameElement(@NotNull PerlSubNameElement o) {
PsiReference reference = o.getReference();
if (reference == null) {
return;
}
if (reference.resolve() != breakDefinition) {
return;
}
PsiElement position = o;
boolean isInsideTheLoop = false;
while (true) {
PsiElement closestBlockContainer = getClosestBlockContainer(position);
if (closestBlockContainer == null) {
break;
}
IElementType blockContainerElementType = PsiUtilCore.getElementType(closestBlockContainer);
if (LOOPS_CONTAINERS.contains(blockContainerElementType)) {
isInsideTheLoop = true;
} else if (blockContainerElementType == NAMED_BLOCK) {
break;
} else if (MAP_GREP.contains(blockContainerElementType)) {
break;
} else if (BLOCKS_WITH_RETURN_VALUE.contains(blockContainerElementType)) {
break;
} else if (blockContainerElementType == GIVEN_COMPOUND) {
return;
}
position = closestBlockContainer;
}
if (isInsideTheLoop) {
holder.registerProblem(o, PerlBundle.message("perl.inspection.loop.control.break.instead.of.last"), new ReplaceWithExpressionQuickFix("last"));
} else {
problem(o, "perl.inspection.loop.control.break");
}
}
private void problem(@NotNull PsiElement anchor, @NotNull String key, @NotNull String... args) {
registerProblem(holder, anchor, PerlBundle.message(key, (Object[]) args));
}
/**
* @return parent psi element for closest parent block element
*/
@Nullable
private PsiElement getClosestBlockContainer(@NotNull PsiElement position) {
PsiPerlBlock enclosingBlock = PsiTreeUtil.getParentOfType(position, PsiPerlBlock.class);
if (enclosingBlock == null) {
return null;
}
PsiElement blockContainer = enclosingBlock.getParent();
return PsiUtilCore.getElementType(blockContainer) == LP_CODE_BLOCK ? blockContainer.getParent() : blockContainer;
}
/**
* Traversing blocks up, trying to figure out if last/next/redo are in right place.
*
* @param expr last/next/redo expression
*/
private void processLoopsControl(@NotNull PsiElement expr) {
PsiElement keyword = expr.getFirstChild();
if (keyword == null) {
return;
}
String keywordText = keyword.getText();
// checks modifier
PsiPerlStatementImpl containingStatement = PsiTreeUtil.getParentOfType(expr, PsiPerlStatementImpl.class);
PsiPerlStatementModifier modifier = containingStatement == null ? null : containingStatement.getModifier();
if (modifier instanceof PsiPerlForStatementModifier) {
return;
}
// traversing up
PsiElement position = expr;
boolean isInsideGiven = false;
boolean isInsideWhenOrDefault = false;
while (true) {
PsiElement closestBlockContainer = getClosestBlockContainer(position);
if (closestBlockContainer == null) {
break;
}
IElementType blockContainerType = PsiUtilCore.getElementType(closestBlockContainer);
if (LOOPS_CONTAINERS.contains(blockContainerType)) {
return;
} else if (blockContainerType == NAMED_BLOCK) {
problem(expr, "perl.inspection.loop.control.in.named.block", keywordText);
return;
} else if (MAP_GREP.contains(blockContainerType)) {
problem(expr, "perl.inspection.loop.control.in.map", keywordText);
return;
} else if (BLOCKS_WITH_RETURN_VALUE.contains(blockContainerType)) {
problem(expr, "perl.inspection.loop.control.in.do", keywordText);
return;
} else if (blockContainerType == GIVEN_COMPOUND) {
isInsideGiven = true;
} else if (blockContainerType == WHEN_COMPOUND || blockContainerType == DEFAULT_COMPOUND) {
isInsideWhenOrDefault = true;
}
position = closestBlockContainer;
}
if (expr instanceof PsiPerlNextExpr && isInsideWhenOrDefault) {
holder.registerProblem(expr, PerlBundle.message("perl.inspection.loop.control.next.instead.of.continue"), new ReplaceWithExpressionQuickFix("continue"));
} else if (expr instanceof PsiPerlLastExpr && isInsideGiven) {
holder.registerProblem(expr, PerlBundle.message("perl.inspection.loop.control.last.instead.of.break"), new ReplaceWithExpressionQuickFix("break"));
} else {
problem(expr, "perl.inspection.loop.control.outside", keywordText);
}
}
};
}
use of com.perl5.lang.perl.psi.PerlSubDefinitionElement in project Perl5-IDEA by Camelcade.
the class PerlMultipleSubDefinitionsInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new PerlVisitor() {
@Override
public void visitPerlSubDefinitionElement(@NotNull PerlSubDefinitionElement o) {
Project project = o.getProject();
String name = "Sub";
String canonicalName = o.getCanonicalName();
if (PerlSubUtil.getSubDefinitions(project, canonicalName, GlobalSearchScope.projectScope(project)).size() > 1) {
if (!PerlPackageUtil.isMain(o.getPackageName()) || !PerlSharedSettings.getInstance(project).SIMPLE_MAIN_RESOLUTION) {
registerProblem(holder, o.getNameIdentifier(), String.format("Multiple %ss definitions found", name.toLowerCase()));
}
}
super.visitPerlSubDefinitionElement(o);
}
};
}
use of com.perl5.lang.perl.psi.PerlSubDefinitionElement in project Perl5-IDEA by Camelcade.
the class PerlStructureViewElement method getChildren.
@NotNull
@Override
public TreeElement[] getChildren() {
List<TreeElement> result = new ArrayList<>();
Set<String> implementedMethods = new HashSet<>();
if (myElement instanceof PerlFile) {
FileViewProvider viewProvider = ((PerlFile) myElement).getViewProvider();
PsiFile podFile = viewProvider.getPsi(PodLanguage.INSTANCE);
if (podFile != null && podFile.getChildren().length > 1) {
result.add(new PodStructureViewElement(podFile));
}
Language targetLanguage = null;
for (Language language : viewProvider.getLanguages()) {
if (language == PerlLanguage.INSTANCE) {
targetLanguage = language;
break;
} else if (targetLanguage == null && language.isKindOf(PerlLanguage.INSTANCE)) {
targetLanguage = language;
}
}
if (targetLanguage != null) {
viewProvider.getPsi(targetLanguage).accept(new PerlRecursiveVisitor() {
@Override
public void visitNamespaceDefinitionElement(@NotNull PerlNamespaceDefinitionElement o) {
result.add(new PerlNamespaceStructureViewElement(o));
super.visitNamespaceDefinitionElement(o);
}
});
}
}
if (myElement instanceof PerlNamespaceDefinitionElement) {
// global variables
for (PerlVariableDeclarationElement child : PsiTreeUtil.findChildrenOfType(myElement, PerlVariableDeclarationElement.class)) {
if (child.isGlobalDeclaration() && myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
result.add(new PerlVariableDeclarationStructureViewElement(child));
}
}
Project project = myElement.getProject();
GlobalSearchScope projectScope = GlobalSearchScope.projectScope(project);
// imported scalars
for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedScalarDescriptors()) {
String canonicalName = exportDescritptor.getTargetCanonicalName();
Collection<PerlVariableDeclarationElement> variables = PerlScalarUtil.getGlobalScalarDefinitions(project, canonicalName);
for (PerlVariableDeclarationElement variable : variables) {
result.add(new PerlVariableDeclarationStructureViewElement(variable).setImported(exportDescritptor));
}
// globs
Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
if (items.isEmpty()) {
items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
}
for (PerlGlobVariable item : items) {
result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
}
}
// imported arrays
for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedArrayDescriptors()) {
String canonicalName = exportDescritptor.getTargetCanonicalName();
Collection<PerlVariableDeclarationElement> variables = PerlArrayUtil.getGlobalArrayDefinitions(project, canonicalName);
for (PerlVariableDeclarationElement variable : variables) {
result.add(new PerlVariableDeclarationStructureViewElement(variable).setImported(exportDescritptor));
}
// globs
Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
if (items.isEmpty()) {
items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
}
for (PerlGlobVariable item : items) {
result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
}
}
// imported hashes
for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedHashDescriptors()) {
String canonicalName = exportDescritptor.getTargetCanonicalName();
Collection<PerlVariableDeclarationElement> variables = PerlHashUtil.getGlobalHashDefinitions(project, canonicalName);
for (PerlVariableDeclarationElement variable : variables) {
result.add(new PerlVariableDeclarationStructureViewElement(variable).setImported(exportDescritptor));
}
// globs
Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
if (items.isEmpty()) {
items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
}
for (PerlGlobVariable item : items) {
result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
}
}
// Imported subs
for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedSubsDescriptors()) {
String canonicalName = exportDescritptor.getTargetCanonicalName();
// declarations
Collection<PerlSubDeclarationElement> subDeclarations = PerlSubUtil.getSubDeclarations(project, canonicalName, projectScope);
if (subDeclarations.isEmpty()) {
subDeclarations = PerlSubUtil.getSubDeclarations(project, canonicalName);
}
for (PerlSubDeclarationElement item : subDeclarations) {
result.add(new PerlSubStructureViewElement(item).setImported(exportDescritptor));
}
// definitions
Collection<PerlSubDefinitionElement> subDefinitions = PerlSubUtil.getSubDefinitions(project, canonicalName, projectScope);
if (subDefinitions.isEmpty()) {
subDefinitions = PerlSubUtil.getSubDefinitions(project, canonicalName);
}
for (PerlSubDefinitionElement item : subDefinitions) {
result.add(new PerlSubStructureViewElement(item).setImported(exportDescritptor));
}
// globs
Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
if (items.isEmpty()) {
items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
}
for (PerlGlobVariable item : items) {
result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
}
}
myElement.accept(new PerlRecursiveVisitor() {
@Override
public void visitPerlSubDefinitionElement(@NotNull PerlSubDefinitionElement child) {
if (myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
implementedMethods.add(child.getName());
result.add(new PerlSubStructureViewElement(child));
}
super.visitPerlSubDefinitionElement(child);
}
@Override
public void visitSubDeclarationElement(@NotNull PerlSubDeclarationElement child) {
if (myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
result.add(new PerlSubStructureViewElement(child));
}
super.visitSubDeclarationElement(child);
}
@Override
public void visitGlobVariable(@NotNull PsiPerlGlobVariable child) {
if (child.isLeftSideOfAssignment() && myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
implementedMethods.add(child.getName());
result.add(new PerlGlobStructureViewElement(child));
}
super.visitGlobVariable(child);
}
});
}
// inherited elements
if (myElement instanceof PerlNamespaceDefinitionWithIdentifier) {
List<TreeElement> inheritedResult = new ArrayList<>();
String packageName = ((PerlNamespaceDefinitionElement) myElement).getPackageName();
if (packageName != null) {
for (PsiElement element : PerlMro.getVariants(myElement, packageName, true)) {
if (element instanceof PerlIdentifierOwner && !implementedMethods.contains(((PerlIdentifierOwner) element).getName())) {
if (element instanceof PerlLightConstantDefinitionElement) {
inheritedResult.add(new PerlSubStructureViewElement((PerlSubDefinitionElement) element).setInherited());
} else if (element instanceof PerlSubDefinitionElement) {
inheritedResult.add(new PerlSubStructureViewElement((PerlSubDefinitionElement) element).setInherited());
} else if (element instanceof PerlSubDeclarationElement) {
inheritedResult.add(new PerlSubStructureViewElement((PerlSubDeclarationElement) element).setInherited());
} else if (element instanceof PerlGlobVariable && ((PerlGlobVariable) element).isLeftSideOfAssignment() && ((PerlGlobVariable) element).getName() != null) {
inheritedResult.add(new PerlGlobStructureViewElement((PerlGlobVariable) element).setInherited());
}
}
}
}
if (!inheritedResult.isEmpty()) {
result.addAll(0, inheritedResult);
}
}
return result.toArray(new TreeElement[result.size()]);
}
Aggregations