use of com.perl5.lang.perl.psi.PerlMethod 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.PerlMethod 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()]);
}
use of com.perl5.lang.perl.psi.PerlMethod in project Perl5-IDEA by Camelcade.
the class PerlFancyMethodQuickFix method applyFix.
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement method = descriptor.getPsiElement();
assert method instanceof PerlMethod;
PsiElement currentCallExpression = method.getParent();
assert currentCallExpression instanceof PsiPerlSubCallExpr;
// fixme ok, this is works, but we make syntax tree invalid, will be updated with next reparsing. Not sure it's a problem
PerlNamespaceElement namespaceElement = ((PerlMethod) method).getNamespaceElement();
assert namespaceElement != null;
PerlSubNameElement subNameElement = ((PerlMethod) method).getSubNameElement();
assert subNameElement != null;
method.replace(PerlElementFactory.createMethodCall(project, namespaceElement.getCanonicalName(), subNameElement.getName()));
}
use of com.perl5.lang.perl.psi.PerlMethod in project Perl5-IDEA by Camelcade.
the class PerlAnnotator method annotate.
@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
IElementType elementType = PsiUtilCore.getElementType(element);
if (elementType == NYI_STATEMENT) {
holder.createInfoAnnotation(element, "Unimplemented statement").setTextAttributes(CodeInsightColors.TODO_DEFAULT_ATTRIBUTES);
} else if (element instanceof PerlGlobVariable && ((PerlGlobVariable) element).isBuiltIn()) {
holder.createInfoAnnotation(element, null).setTextAttributes(PERL_GLOB_BUILTIN);
} else if (element instanceof PerlVariable && ((PerlVariable) element).isBuiltIn()) {
holder.createInfoAnnotation(element, null).setTextAttributes(VARIABLE_KEYS_MAP.get(element.getClass()));
} else if (elementType == LABEL_DECLARATION || elementType == LABEL_EXPR) {
holder.createInfoAnnotation(element.getFirstChild(), null).setTextAttributes(PerlSyntaxHighlighter.PERL_LABEL);
} else if (elementType == PACKAGE) {
assert element instanceof PerlNamespaceElement;
PerlNamespaceElement namespaceElement = (PerlNamespaceElement) element;
PsiElement parent = namespaceElement.getParent();
if (parent instanceof PerlNamespaceDefinitionWithIdentifier) {
decorateElement(namespaceElement, holder, PerlSyntaxHighlighter.PERL_PACKAGE_DEFINITION, false);
} else {
if (namespaceElement.isPragma()) {
decorateElement(namespaceElement, holder, PerlSyntaxHighlighter.PERL_PACKAGE_PRAGMA, false);
} else if (namespaceElement.isBuiltin()) {
decorateElement(namespaceElement, holder, PerlSyntaxHighlighter.PERL_PACKAGE_CORE, false);
}
}
} else if (element instanceof PerlPolyNamedElement) {
TextAttributesKey subAttribute = PerlSyntaxHighlighter.PERL_SUB_DEFINITION;
if (elementType == PerlConstantsWrapperElementType.CONSTANT_WRAPPER) {
// fixme some interface?
subAttribute = PerlSyntaxHighlighter.PERL_CONSTANT;
}
for (PerlDelegatingLightNamedElement lightNamedElement : ((PerlPolyNamedElement) element).getLightElements()) {
TextAttributesKey currentKey = lightNamedElement instanceof PerlSubDefinition ? subAttribute : PerlSyntaxHighlighter.PERL_PACKAGE_DEFINITION;
PsiElement navigationElement = lightNamedElement.getNavigationElement();
holder.createInfoAnnotation(ElementManipulators.getValueTextRange(navigationElement).shiftRight(lightNamedElement.getTextOffset()), null).setEnforcedTextAttributes(adjustTextAttributes(currentScheme.getAttributes(currentKey), false));
}
} else if (// instanceof PerlSubNameElement
elementType == SUB_NAME) {
PsiElement parent = element.getParent();
if (parent instanceof PsiPerlSubDeclaration) {
holder.createInfoAnnotation(element, null).setTextAttributes(PerlSyntaxHighlighter.PERL_SUB_DECLARATION);
} else if (parent instanceof PerlSubDefinitionElement) {
if ("AUTOLOAD".equals(((PerlSubNameElement) element).getName())) {
holder.createInfoAnnotation(element, null).setTextAttributes(PerlSyntaxHighlighter.PERL_AUTOLOAD);
} else {
holder.createInfoAnnotation(element, null).setTextAttributes(PerlSyntaxHighlighter.PERL_SUB_DEFINITION);
}
} else if (parent instanceof PerlMethod) {
// fixme don't we need to take multiple references here?
PsiElement grandParent = parent.getParent();
PerlNamespaceElement methodNamespace = ((PerlMethod) parent).getNamespaceElement();
if (// / not ...->method fixme shouldn't we use isObjectMethod here?
!(grandParent instanceof PsiPerlNestedCall) && // no explicit NS or it's core
(methodNamespace == null || methodNamespace.isCORE()) && ((PerlSubNameElement) element).isBuiltIn()) {
decorateElement(element, holder, PerlSyntaxHighlighter.PERL_SUB_BUILTIN);
} else {
PsiReference reference = element.getReference();
if (reference instanceof PerlSubReference) {
((PerlSubReference) reference).multiResolve(false);
if (((PerlSubReference) reference).isConstant()) {
holder.createInfoAnnotation(element, "Constant").setTextAttributes(PerlSyntaxHighlighter.PERL_CONSTANT);
} else if (((PerlSubReference) reference).isAutoloaded()) {
holder.createInfoAnnotation(element, "Auto-loaded sub").setTextAttributes(PerlSyntaxHighlighter.PERL_AUTOLOAD);
} else if (((PerlSubReference) reference).isXSub()) {
holder.createInfoAnnotation(element, "XSub").setTextAttributes(PerlSyntaxHighlighter.PERL_XSUB);
}
}
}
}
}
}
use of com.perl5.lang.perl.psi.PerlMethod in project Perl5-IDEA by Camelcade.
the class PerlSubUtil method getMethodReturnValue.
/**
* Detects return value of method container
*
* @param methodContainer method container inspected
* @return package name or null
*/
@Nullable
public static String getMethodReturnValue(PerlMethodContainer methodContainer) {
if (methodContainer instanceof PerlSmartMethodContainer) {
return ((PerlSmartMethodContainer) methodContainer).getReturnPackageName();
}
PerlMethod methodElement = methodContainer.getMethod();
if (methodElement == null) {
return null;
}
PerlSubNameElement subNameElement = methodElement.getSubNameElement();
if (subNameElement == null) {
return null;
}
if ("new".equals(subNameElement.getName())) {
return methodElement.getPackageName();
}
PsiReference reference = subNameElement.getReference();
if (reference instanceof PerlSubReference) {
for (ResolveResult resolveResult : ((PerlSubReference) reference).multiResolve(false)) {
PsiElement targetElement = resolveResult.getElement();
if (targetElement instanceof PerlSub) {
String returnType = ((PerlSub) targetElement).getReturns(subNameElement.getPackageName(), methodContainer.getCallArgumentsList());
if (returnType != null) {
return returnType;
}
}
}
}
return null;
}
Aggregations