use of com.perl5.lang.perl.psi.impl.PerlSubCallElement in project Perl5-IDEA by Camelcade.
the class MojoHelperHandler method computeLightElementsFromPsi.
@Override
@NotNull
public List<? extends PerlDelegatingLightNamedElement<?>> computeLightElementsFromPsi(@NotNull PerlSubCallElement psiElement) {
List<PsiElement> listElements = psiElement.getCallArgumentsList();
if (listElements.size() != 2) {
return Collections.emptyList();
}
PsiElement identifierElement = listElements.get(0);
if (!psiElement.isAcceptableIdentifierElement(identifierElement)) {
return Collections.emptyList();
}
PsiElement bodyElement = listElements.get(1);
if (!(bodyElement instanceof PerlSubExpr)) {
return Collections.emptyList();
}
String subName = ElementManipulators.getValueText(identifierElement);
if (StringUtil.isEmpty(subName)) {
return Collections.emptyList();
}
return Collections.singletonList(new MojoHelperDefinition(psiElement, subName, LIGHT_METHOD_DEFINITION, identifierElement, MOJO_CONTROLLER_NS, (PerlSubExpr) bodyElement));
}
use of com.perl5.lang.perl.psi.impl.PerlSubCallElement in project Perl5-IDEA by Camelcade.
the class PerlMooseAttributeHandler method createMooseAttributes.
@NotNull
private List<PerlDelegatingLightNamedElement<?>> createMooseAttributes(@NotNull PerlSubCallElement subCallElement, @NotNull List<PsiElement> identifiers, @NotNull List<PsiElement> listElements) {
List<PerlDelegatingLightNamedElement<?>> result = new ArrayList<>();
String packageName = PerlPackageUtil.getContextNamespaceName(subCallElement);
Map<String, PerlHashEntry> parameters = PerlHashUtil.packToHash(listElements.subList(1, listElements.size()));
// handling is
PerlHashEntry isParameter = parameters.get(IS_KEY);
boolean isWritableProtected = isParameter != null && StringUtil.equals(RWP_KEY, isParameter.getValueString());
boolean isWritable = isParameter != null && (StringUtil.equals(RW_KEY, isParameter.getValueString()) || isWritableProtected);
PsiElement forcedIdentifier = null;
// handling isa and does
PerlHashEntry isaEntry = parameters.get(ISA_KEY);
String valueClass = null;
if (isaEntry == null) {
isaEntry = parameters.get(DOES_KEY);
}
if (isaEntry != null && subCallElement.isAcceptableIdentifierElement(isaEntry.valueElement)) {
valueClass = isaEntry.getValueString();
if (StringUtil.isEmpty(valueClass)) {
valueClass = null;
}
}
// handling accessor, reader, etc.
boolean createMooClearer = false;
boolean createMooPredicate = false;
List<PerlLightMethodDefinitionElement<?>> secondaryResult = new ArrayList<>();
for (String key : MOOSE_SUB_NAMES_KEYS) {
PerlHashEntry entry = parameters.get(key);
if (entry == null) {
continue;
}
String methodName = entry.getValueString();
if (StringUtil.isEmpty(methodName)) {
if (entry.valueElement instanceof PsiPerlNumberConstant && "1".equals(entry.valueElement.getText())) {
if (key.equals(CLEARER_KEY)) {
createMooClearer = true;
} else if (key.equals(PREDICATE_KEY)) {
createMooPredicate = true;
}
}
continue;
}
if (!isWritable && key.equals(WRITER_KEY)) {
continue;
}
if (!isWritable && key.equals(READER_KEY) || key.equals(ACCESSOR_KEY)) {
forcedIdentifier = entry.valueElement;
continue;
}
if (!subCallElement.isAcceptableIdentifierElement(entry.valueElement)) {
continue;
}
// fixme we could optimize new_value with subclassing and hardcoding of signature
PsiElement identifier = entry.getNonNullValueElement();
PerlLightMethodDefinitionElement<PerlSubCallElement> secondaryElement = new PerlLightMethodDefinitionElement<>(subCallElement, ElementManipulators.getValueText(identifier), LIGHT_METHOD_DEFINITION, identifier, packageName, key.equals(WRITER_KEY) ? Arrays.asList(PerlSubArgument.self(), PerlSubArgument.optionalScalar(PerlSubArgument.NEW_VALUE_VALUE, valueClass)) : Collections.emptyList(), PerlSubAnnotations.tryToFindAnnotations(identifier, entry.keyElement, subCallElement.getParent()));
if (key.equals(READER_KEY) && valueClass != null) {
secondaryElement.setReturnValueFromCode(PerlScalarValue.create(valueClass));
}
secondaryResult.add(secondaryElement);
}
// handle handles
PerlHashEntry handlesEntry = parameters.get(HANDLES_KEY);
if (handlesEntry != null) {
// to show proper signatures, we need an access to delegates, what requires indexes; we should do this in runtime, not indexing, but store delegation target
if (handlesEntry.valueElement instanceof PsiPerlAnonHash) {
// handle handles HASH
Map<String, PerlHashEntry> delegatesMap = PerlHashUtil.collectHashMap(handlesEntry.valueElement);
for (PerlHashEntry delegateEntry : delegatesMap.values()) {
if (!subCallElement.isAcceptableIdentifierElement(delegateEntry.keyElement)) {
continue;
}
secondaryResult.add(new PerlLightMethodDefinitionElement<>(subCallElement, ElementManipulators.getValueText(delegateEntry.keyElement), LIGHT_METHOD_DEFINITION, delegateEntry.keyElement, packageName, Collections.emptyList(), PerlSubAnnotations.tryToFindAnnotations(delegateEntry.keyElement, handlesEntry.keyElement, subCallElement.getParent())));
}
} else if (handlesEntry.valueElement instanceof PsiPerlAnonArray) {
// handle handles ARRAY
List<PsiElement> delegatesIdentifiers = PerlArrayUtil.collectListElements(((PsiPerlAnonArray) handlesEntry.valueElement).getExpr());
for (PsiElement identifier : delegatesIdentifiers) {
if (!subCallElement.isAcceptableIdentifierElement(identifier)) {
continue;
}
secondaryResult.add(new PerlLightMethodDefinitionElement<>(subCallElement, ElementManipulators.getValueText(identifier), LIGHT_METHOD_DEFINITION, identifier, packageName, Collections.emptyList(), PerlSubAnnotations.tryToFindAnnotations(identifier, handlesEntry.keyElement, subCallElement.getParent())));
}
}
}
for (PsiElement identifier : identifiers) {
if (forcedIdentifier != null) {
identifier = forcedIdentifier;
}
if (!subCallElement.isAcceptableIdentifierElement(identifier)) {
continue;
}
List<PerlSubArgument> subArguments = isWritable && !isWritableProtected ? Arrays.asList(PerlSubArgument.self(), PerlSubArgument.optionalScalar(PerlSubArgument.NEW_VALUE_VALUE, valueClass)) : Collections.emptyList();
var identifierText = ElementManipulators.getValueText(identifier);
var identifierAnnotations = PerlSubAnnotations.tryToFindAnnotations(identifier, subCallElement.getParent());
PerlAttributeDefinition newElement = new PerlAttributeDefinition(subCallElement, PerlAttributeDefinition.DEFAULT_NAME_COMPUTATION.fun(identifierText), LIGHT_ATTRIBUTE_DEFINITION, identifier, packageName, subArguments, identifierAnnotations);
if (valueClass != null) {
PerlValue returnValue = PerlScalarValue.create(valueClass);
newElement.setReturnValueFromCode(returnValue);
}
result.add(newElement);
if (isWritableProtected) {
result.add(new PerlLightMethodDefinitionElement<>(subCallElement, PROTECTED_MUTATOR_PREFIX + identifierText, LIGHT_METHOD_DEFINITION, identifier, packageName, Arrays.asList(PerlSubArgument.self(), PerlSubArgument.mandatoryScalar(PerlSubArgument.NEW_VALUE_VALUE, StringUtil.notNullize(valueClass))), identifierAnnotations));
}
if (createMooClearer) {
var clearerName = identifierText.startsWith("_") ? _MOO_CLEARER_PREFIX + identifierText.substring(1) : MOO_CLEARER_PREFIX + identifierText;
result.add(new PerlLightMethodDefinitionElement<>(subCallElement, clearerName, LIGHT_METHOD_DEFINITION, identifier, packageName, Collections.emptyList(), identifierAnnotations));
}
if (createMooPredicate) {
var predicateName = identifierText.startsWith("_") ? _MOO_PREDICATE_PREFIX + identifierText.substring(1) : MOO_PREDICATE_PREFIX + identifierText;
result.add(new PerlLightMethodDefinitionElement<>(subCallElement, predicateName, LIGHT_METHOD_DEFINITION, identifier, packageName, Collections.emptyList(), identifierAnnotations));
}
result.addAll(secondaryResult);
secondaryResult.clear();
}
return result;
}
use of com.perl5.lang.perl.psi.impl.PerlSubCallElement in project Perl5-IDEA by Camelcade.
the class PerlNameSuggestionProvider method suggestAndGetForDereference.
private String suggestAndGetForDereference(@NotNull PsiElement expression, @NotNull Set<String> result, String recommendation) {
PsiElement[] children = expression.getChildren();
PsiElement element = children[children.length - 1];
PsiElement baseElement = children[children.length - 2];
if (element instanceof PsiPerlHashIndex) {
recommendation = Objects.requireNonNull(join(HASH, ELEMENT));
result.add(recommendation);
result.add(join(HASH, ITEM));
recommendation = suggestNamesForElements(baseElement, true, ((PsiPerlHashIndex) element).getExpr(), result, recommendation);
} else if (element instanceof PsiPerlArrayIndex) {
recommendation = Objects.requireNonNull(join(ARRAY, ELEMENT));
result.add(recommendation);
result.add(join(ARRAY, ITEM));
recommendation = suggestNamesForElements(baseElement, true, ((PsiPerlArrayIndex) element).getExpr(), result, recommendation);
} else if (element instanceof PerlSubCallElement) {
recommendation = suggestAndGetForCall((PerlSubCallElement) element, result, recommendation);
} else if (element instanceof PsiPerlParenthesisedCallArguments) {
recommendation = join(getBaseName(baseElement), RESULT);
}
return recommendation;
}
use of com.perl5.lang.perl.psi.impl.PerlSubCallElement in project Perl5-IDEA by Camelcade.
the class PerlNameSuggestionProvider method suggestAndGetForCall.
private static String suggestAndGetForCall(@NotNull PerlSubCallElement subCall, @NotNull Set<String> result, String recommendation) {
PsiPerlMethod method = subCall.getMethod();
if (method == null) {
return recommendation;
}
PerlCallValue callValue = PerlCallValue.from(method);
if (callValue == null) {
return recommendation;
}
PerlValue subNameValue = callValue.getSubNameValue();
if (subNameValue.canRepresentSubName("new")) {
PerlValue namespaceNameValue = callValue.getNamespaceNameValue();
Collection<String> variantsFromObjectClass = getVariantsFromPerlValueNamespaces(method, namespaceNameValue);
result.addAll(variantsFromObjectClass);
if (!variantsFromObjectClass.isEmpty()) {
recommendation = variantsFromObjectClass.iterator().next();
}
} else {
Ref<String> recommendationRef = Ref.create(recommendation);
for (String subName : subNameValue.resolve(method).getSubNames()) {
String normalizedName = join(subName.replaceAll("^(_+|get_*|set_*)", ""));
if (StringUtil.isNotEmpty(normalizedName)) {
result.add(normalizedName);
recommendationRef.set(normalizedName);
}
}
recommendation = recommendationRef.get();
result.addAll(getVariantsFromEntityValueNamespaces(subCall));
}
return recommendation;
}
use of com.perl5.lang.perl.psi.impl.PerlSubCallElement in project Perl5-IDEA by Camelcade.
the class PerlClassAccessorHandler method isFollowBestPractice.
static boolean isFollowBestPractice(@NotNull PerlSubCallElement psiElement) {
PerlSubCallElementStub stub = psiElement.getGreenStub();
if (stub != null) {
PerlSubCallElementData callData = stub.getCallData();
LOG.assertTrue(callData instanceof PerlClassAccessorCallData, "Got: " + callData);
return ((PerlClassAccessorCallData) callData).isFBP();
}
return CachedValuesManager.getCachedValue(psiElement, () -> {
Ref<Boolean> result = Ref.create(Boolean.FALSE);
// fixme we need a smarter treewalkup here, scopes are not necessary here
PerlResolveUtil.treeWalkUp(psiElement, (element, state) -> {
if (element instanceof PsiPerlNamespaceContent) {
return false;
}
if (element instanceof PerlSubCallElement && StringUtil.equals("follow_best_practice", ((PerlSubCallElement) element).getSubName())) {
result.set(Boolean.TRUE);
return false;
}
return true;
});
return CachedValueProvider.Result.create(result.get(), psiElement);
}) == Boolean.TRUE;
}
Aggregations