use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.
the class PerlFancyMethodCallInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new PerlVisitor() {
@Override
public void visitMethod(@NotNull PsiPerlMethod o) {
if (o.isObjectMethod() && o.getLastChild() instanceof PerlNamespaceElement) {
String packageName = o.getPackageName();
if (packageName == null) {
return;
}
PerlSubNameElement subNameElement = o.getSubNameElement();
if (subNameElement == null) {
return;
}
String properForm = String.format("%s->%s", packageName, subNameElement.getName());
holder.registerProblem(o, PerlBundle.message("perl.inspection.fancy.call", properForm), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new PerlFancyMethodQuickFix(properForm));
}
}
};
}
use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.
the class PerlDocumentationProvider method getCustomDocumentationElement.
@Nullable
@Override
public PsiElement getCustomDocumentationElement(@NotNull Editor editor, @NotNull PsiFile file, @Nullable PsiElement contextElement) {
if (contextElement == null || contextElement.getLanguage() != PerlLanguage.INSTANCE) {
return null;
}
IElementType elementType = contextElement.getNode().getElementType();
if (contextElement instanceof PerlVariable) {
// fixme try to search doc in package or declaration
return PerlDocUtil.getPerlVarDoc((PerlVariable) contextElement);
} else if (elementType == REGEX_MODIFIER) {
return PerlDocUtil.getRegexModifierDoc(contextElement);
} else if (elementType == REGEX_TOKEN) {
return PerlDocUtil.resolveDocLink("perlretut", contextElement);
} else if (elementType == VERSION_ELEMENT) {
return PerlDocUtil.resolveDocLink("perldata/\"Version Strings\"", contextElement);
} else if (isFunc(contextElement)) {
return PerlDocUtil.getPerlFuncDoc(contextElement);
} else if (isOp(contextElement)) {
return PerlDocUtil.getPerlOpDoc(contextElement);
} else if (contextElement instanceof PerlSubNameElement) {
String packageName = ((PerlSubNameElement) contextElement).getPackageName();
String subName = ((PerlSubNameElement) contextElement).getName();
if (StringUtil.isNotEmpty(subName)) {
PsiElement result = null;
// search by link
if (StringUtil.isNotEmpty(packageName) && !StringUtil.equals(PerlPackageUtil.MAIN_PACKAGE, packageName)) {
result = PerlDocUtil.resolveDocLink(packageName + "/" + ((PerlSubNameElement) contextElement).getName(), contextElement);
}
// not found or main::
if (result == null) {
PsiElement target = null;
if (contextElement.getParent() instanceof PerlSubElement) {
target = contextElement.getParent();
} else {
PsiReference reference = contextElement.getReference();
if (reference != null) {
target = reference.resolve();
}
}
if (target != null) {
PsiFile targetFile = target.getContainingFile();
if (targetFile != null) {
PsiFile podFile = targetFile.getViewProvider().getPsi(PodLanguage.INSTANCE);
if (podFile != null) {
result = PerlDocUtil.searchPodElement(targetFile, PodDocumentPattern.headingAndItemPattern(subName));
}
}
}
}
if (result != null) {
return result;
}
}
} else if (contextElement instanceof PerlNamespaceElement) {
String packageName = ((PerlNamespaceElement) contextElement).getCanonicalName();
if (StringUtil.equals(PerlPackageUtil.SUPER_PACKAGE, packageName)) {
return PerlDocUtil.resolveDocLink("perlobj/Inheritance", contextElement);
} else if (StringUtil.isNotEmpty(packageName)) {
return PerlDocUtil.resolveDocLink(packageName, contextElement);
}
}
return super.getCustomDocumentationElement(editor, file, contextElement);
}
use of com.perl5.lang.perl.psi.PerlSubNameElement 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.PerlSubNameElement in project Perl5-IDEA by Camelcade.
the class PerlUnresolvedSubInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new PerlVisitor() {
@Override
public void visitStringContentElement(@NotNull PerlStringContentElementImpl o) {
if (EXPORT_ASSIGNED_STRING_CONTENT.accepts(o)) {
if (!isResolvable(o.getReference())) {
registerProblem(holder, o, PerlBundle.message("perl.inspection.no.exported.entity"));
}
}
}
@Override
public void visitPerlMethod(@NotNull PerlMethod o) {
PerlNamespaceElement namespaceElement = o.getNamespaceElement();
PerlSubNameElement subNameElement = o.getSubNameElement();
// fixme adjust built in checking to the file; Remove second condition after implementing annotations
if (subNameElement == null || namespaceElement != null && namespaceElement.isBuiltin() || subNameElement.isBuiltIn()) {
return;
}
for (PsiReference reference : subNameElement.getReferences()) {
if (isResolvable(reference)) {
return;
}
}
registerProblem(holder, subNameElement, PerlBundle.message("perl.inspection.no.sub.definition"));
}
};
}
use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.
the class PerlSubReference method resolveInner.
@NotNull
@Override
protected ResolveResult[] resolveInner(boolean incompleteCode) {
PsiElement myElement = getElement();
assert myElement instanceof PerlSubNameElement;
PsiElement parent = myElement.getParent();
if (parent instanceof PerlSubDeclarationElement || parent instanceof PerlSubDefinitionElement) {
return ResolveResult.EMPTY_ARRAY;
}
PerlSubNameElement subNameElement = (PerlSubNameElement) myElement;
List<PsiElement> relatedItems = new ArrayList<>();
String packageName = subNameElement.getPackageName();
String subName = subNameElement.getName();
Project project = subNameElement.getProject();
PerlNamespaceElement expliclitPackageElement = null;
if (parent instanceof PerlNamespaceElementContainer) {
expliclitPackageElement = ((PerlNamespaceElementContainer) parent).getNamespaceElement();
}
if (!subName.isEmpty()) {
if (parent instanceof PerlMethod && ((PerlMethod) parent).isObjectMethod()) {
boolean isSuper = expliclitPackageElement != null && expliclitPackageElement.isSUPER();
relatedItems.addAll(PerlMro.resolveSub(project, isSuper ? PerlPackageUtil.getContextPackageName(subNameElement) : packageName, subName, isSuper));
} else // static resolution
{
if (PerlSharedSettings.getInstance(project).SIMPLE_MAIN_RESOLUTION && // fixme this is a dirty hack until proper names resolution implemented
PerlPackageUtil.isMain(packageName)) {
PsiFile file = subNameElement.getContainingFile();
GlobalSearchScope fileScope = GlobalSearchScope.fileScope(file);
collectRelatedItems(packageName + PerlPackageUtil.PACKAGE_SEPARATOR + subName, project, parent, relatedItems, fileScope);
// if (file instanceof PerlFile)
// ((PerlFile) file).getElementsResolveScope();
// System.err.println("Checking for " + subName);
}
if (relatedItems.isEmpty()) {
GlobalSearchScope globalSearchScope = GlobalSearchScope.allScope(project);
// check indexes for defined subs
collectRelatedItems(packageName + PerlPackageUtil.PACKAGE_SEPARATOR + subName, project, parent, relatedItems, globalSearchScope);
if (expliclitPackageElement == null) {
// check for imports to the current file
PerlNamespaceDefinitionElement namespaceContainer = PerlPackageUtil.getNamespaceContainerForElement(subNameElement);
if (namespaceContainer != null) {
for (PerlExportDescriptor exportDescriptor : namespaceContainer.getImportedSubsDescriptors()) {
if (exportDescriptor.getImportedName().equals(subName)) {
int currentSize = relatedItems.size();
collectRelatedItems(exportDescriptor.getTargetCanonicalName(), project, parent, relatedItems, globalSearchScope);
if (// imported, but not found, attempting autoload
relatedItems.size() == currentSize) {
collectRelatedItems(exportDescriptor.getRealPackage() + PerlSubUtil.SUB_AUTOLOAD_WITH_PREFIX, project, parent, relatedItems, globalSearchScope);
}
}
}
}
} else // check imports to target namespace
{
String targetPackageName = expliclitPackageElement.getCanonicalName();
if (targetPackageName != null) {
// fixme partially not DRY with previous block
for (PerlNamespaceDefinitionElement namespaceDefinition : PerlPackageUtil.getNamespaceDefinitions(project, targetPackageName)) {
for (PerlExportDescriptor exportDescriptor : namespaceDefinition.getImportedSubsDescriptors()) {
if (exportDescriptor.getImportedName().equals(subName)) {
collectRelatedItems(exportDescriptor.getTargetCanonicalName(), project, parent, relatedItems, globalSearchScope);
}
}
}
}
}
// check for builtins
if (relatedItems.isEmpty()) {
PerlSubDefinitionElement builtInSub = PerlBuiltInSubsService.getInstance(project).findSub(subName);
if (builtInSub != null) {
relatedItems.add(builtInSub);
}
}
// check for autoload
if (relatedItems.isEmpty() && // don't check for UNIVERSAL::AUTOLOAD
!PerlPackageUtil.isUNIVERSAL(packageName)) {
collectRelatedItems(packageName + PerlSubUtil.SUB_AUTOLOAD_WITH_PREFIX, project, parent, relatedItems, globalSearchScope);
}
}
}
}
List<ResolveResult> result = getResolveResults(relatedItems);
return result.toArray(new ResolveResult[result.size()]);
}
Aggregations