use of com.perl5.lang.perl.psi.PerlVariableDeclarationElement in project Perl5-IDEA by Camelcade.
the class PerlVariableCompletionUtil method fillWithUnresolvedVars.
public static void fillWithUnresolvedVars(@NotNull PerlVariableNameElement variableNameElement, @NotNull CompletionResultSet resultSet) {
final PerlLexicalScope lexicalScope = PsiTreeUtil.getParentOfType(variableNameElement, PerlLexicalScope.class);
PsiElement perlVariable = variableNameElement.getParent();
final Set<String> collectedNames = new THashSet<>();
if (lexicalScope != null && perlVariable instanceof PerlVariable) {
final int minOffset = variableNameElement.getTextOffset();
final PerlVariableType actualType = ((PerlVariable) perlVariable).getActualType();
lexicalScope.accept(new PerlRecursiveVisitor() {
@Override
public void visitPerlVariable(@NotNull PerlVariable perlVariable) {
if (perlVariable.isValid() && !(perlVariable.getParent() instanceof PerlVariableDeclarationElement) && perlVariable.getTextOffset() > minOffset && actualType == perlVariable.getActualType()) {
String variableName = perlVariable.getName();
if (StringUtil.isNotEmpty(variableName) && !collectedNames.contains(variableName) && perlVariable.getLexicalDeclaration() == null) {
collectedNames.add(variableName);
resultSet.addElement(LookupElementBuilder.create(variableName));
}
}
super.visitPerlVariable(perlVariable);
}
});
}
}
use of com.perl5.lang.perl.psi.PerlVariableDeclarationElement in project Perl5-IDEA by Camelcade.
the class PerlXNamedValue method computeMySourcePosition.
protected boolean computeMySourcePosition(@Nullable XNavigatable navigatable, @Nullable final XInlineDebuggerDataCallback callback) {
String name = myPerlValueDescriptor.getName();
if (StringUtil.isEmpty(name) || name.length() < 2) {
return false;
}
final PerlVariableType variableType = PerlVariableType.bySigil(name.charAt(0));
if (variableType == null || variableType == PerlVariableType.CODE) {
return false;
}
final String variableName = name.substring(1);
final XSourcePosition sourcePosition = myStackFrame.getSourcePosition();
if (sourcePosition == null) {
return false;
}
final Project project = myStackFrame.getPerlExecutionStack().getSuspendContext().getDebugSession().getProject();
final VirtualFile virtualFile = sourcePosition.getFile();
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
if (!(psiFile instanceof PerlFileImpl)) {
return false;
}
PsiElement element = psiFile.findElementAt(sourcePosition.getOffset());
if (element == null) {
return false;
}
if (navigatable != null) {
PerlVariableDeclarationSearcher variableProcessor = new PerlVariableDeclarationSearcher(variableName, variableType, element);
PerlResolveUtil.treeWalkUp(element, variableProcessor);
PerlVariableDeclarationElement result = variableProcessor.getResult();
if (result == null) {
return false;
}
navigatable.setSourcePosition(XSourcePositionImpl.createByElement(result));
} else if (callback != null) {
final Document document = psiFile.getViewProvider().getDocument();
if (document == null) {
return false;
}
final boolean[] found = new boolean[] { false };
PerlVariableDeclarationSearcher variableProcessor = new PerlVariableDeclarationSearcher(variableName, variableType, element) {
@Override
public boolean execute(@NotNull PsiElement possibleElement, @NotNull ResolveState state) {
boolean result = super.execute(possibleElement, state);
if (!result) {
registerElement(getResult());
} else if (possibleElement instanceof PerlVariable && ((PerlVariable) possibleElement).getActualType() == variableType && StringUtil.equals(variableName, ((PerlVariable) possibleElement).getName())) {
registerElement(possibleElement);
}
return result;
}
private void registerElement(@Nullable PsiElement targetElement) {
if (targetElement == null) {
return;
}
found[0] = true;
try {
if (mySourcePositionMethod != null) {
mySourcePositionMethod.invoke(callback, XSourcePositionImpl.createByElement(targetElement));
} else if (myLegacyMethod != null) {
myLegacyMethod.invoke(callback, virtualFile, document, document.getLineNumber(targetElement.getTextOffset()));
} else {
found[0] = false;
}
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
};
PerlResolveUtil.treeWalkUp(element, variableProcessor);
return found[0];
}
return true;
}
use of com.perl5.lang.perl.psi.PerlVariableDeclarationElement 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()]);
}
use of com.perl5.lang.perl.psi.PerlVariableDeclarationElement in project Perl5-IDEA by Camelcade.
the class PerlVariableMixin method getVariableTypeHeavy.
@Nullable
private String getVariableTypeHeavy() {
if (this instanceof PsiPerlScalarVariable) {
// System.err.println("Guessing type for " + getText() + " at " + getTextOffset());
PerlVariableNameElement variableNameElement = getVariableNameElement();
if (variableNameElement != null) {
// find lexicaly visible declaration and check type
final PerlVariableDeclarationElement declarationWrapper = getLexicalDeclaration();
if (declarationWrapper != null) {
if (declarationWrapper instanceof PerlImplicitVariableDeclaration) {
return ((PerlImplicitVariableDeclaration) declarationWrapper).getVariableClass();
}
if (declarationWrapper.isInvocantDeclaration() || declarationWrapper.isSelf()) {
PerlSelfHinter selfHinter = PsiTreeUtil.getParentOfType(declarationWrapper, PerlSelfHinter.class);
if (selfHinter != null) {
return selfHinter.getSelfNamespace();
}
return PerlPackageUtil.getContextPackageName(declarationWrapper);
}
// check explicit type in declaration
String declarationPackageName = declarationWrapper.getDeclaredType();
if (declarationPackageName != null) {
assert !declarationPackageName.equals("");
return declarationPackageName;
}
// check assignment around declaration
PerlVariableDeclarationExpr declaration = PsiTreeUtil.getParentOfType(declarationWrapper, PerlVariableDeclarationExpr.class);
if (declaration != null) {
if (declaration.getParent() instanceof PsiPerlAssignExpr) {
PsiPerlAssignExpr assignmentExpression = (PsiPerlAssignExpr) declaration.getParent();
List<PsiPerlExpr> assignmentElements = assignmentExpression.getExprList();
if (!assignmentElements.isEmpty()) {
PsiPerlExpr lastExpression = assignmentElements.get(assignmentElements.size() - 1);
if (lastExpression != declaration) {
// source element is on the left side
if (lastExpression instanceof PerlMethodContainer) {
return PerlSubUtil.getMethodReturnValue((PerlMethodContainer) lastExpression);
}
if (lastExpression instanceof PerlDerefExpression) {
return ((PerlDerefExpression) lastExpression).guessType();
}
}
}
}
}
// fixme this is bad, because my $var1 && print $var1 will be valid, but it's not
PerlLexicalScope perlLexicalScope = PsiTreeUtil.getParentOfType(declarationWrapper, PerlLexicalScope.class);
assert perlLexicalScope != null : "Unable to find lexical scope for:" + declarationWrapper.getClass() + " at " + declarationWrapper.getTextOffset() + " in " + declarationWrapper.getContainingFile();
final String[] guessResult = new String[] { null };
int startOffset = declarationWrapper.getTextRange().getEndOffset();
int endOffset = getTextRange().getStartOffset();
if (startOffset < endOffset) {
PerlPsiUtil.processElementsInRange(perlLexicalScope, new TextRange(startOffset, endOffset), element -> {
if (element != PerlVariableMixin.this && element instanceof PsiPerlScalarVariable && element.getParent() instanceof PsiPerlAssignExpr) {
PsiElement variableNameElement1 = ((PsiPerlScalarVariable) element).getVariableNameElement();
if (variableNameElement1 != null && variableNameElement1.getReference() != null && variableNameElement1.getReference().isReferenceTo(declarationWrapper)) {
// found variable assignment
PsiPerlAssignExpr assignmentExpression = (PsiPerlAssignExpr) element.getParent();
List<PsiPerlExpr> assignmentElements = assignmentExpression.getExprList();
if (!assignmentElements.isEmpty()) {
PsiPerlExpr lastExpression = assignmentElements.get(assignmentElements.size() - 1);
if (lastExpression != element && lastExpression.getTextOffset() < getTextOffset()) {
// source element is on the left side
// fixme implement variables assignment support. Need to build kinda visitor with recursion control
String returnValue = null;
if (lastExpression instanceof PerlMethodContainer) {
returnValue = PerlSubUtil.getMethodReturnValue((PerlMethodContainer) lastExpression);
}
if (lastExpression instanceof PerlDerefExpression) {
returnValue = ((PerlDerefExpression) lastExpression).guessType();
}
if (StringUtil.isNotEmpty(returnValue)) {
guessResult[0] = returnValue;
return false;
}
}
}
}
}
return true;
});
}
if (guessResult[0] != null) {
return guessResult[0];
}
}
// checking global declarations with explicit types
for (PerlVariableDeclarationElement declaration : getGlobalDeclarations()) {
if (declaration.getDeclaredType() != null) {
return declaration.getDeclaredType();
}
}
}
}
return null;
}
use of com.perl5.lang.perl.psi.PerlVariableDeclarationElement in project Perl5-IDEA by Camelcade.
the class PerlVariableMixin method getGlobalDeclarations.
// fixme this need to be moved to PerlResolveUtil or Resolver
@Override
public List<PerlVariableDeclarationElement> getGlobalDeclarations() {
List<PerlVariableDeclarationElement> result = new ArrayList<>();
PerlVariableType myType = getActualType();
// wrapper if any
PsiElement parent = getParent();
if (myType == PerlVariableType.SCALAR) {
for (PerlVariableDeclarationElement variable : PerlScalarUtil.getGlobalScalarDefinitions(getProject(), getCanonicalName())) {
if (!variable.equals(parent)) {
result.add(variable);
}
}
} else if (myType == PerlVariableType.ARRAY) {
for (PerlVariableDeclarationElement variable : PerlArrayUtil.getGlobalArrayDefinitions(getProject(), getCanonicalName())) {
if (!variable.equals(parent)) {
result.add(variable);
}
}
} else if (myType == PerlVariableType.HASH) {
for (PerlVariableDeclarationElement variable : PerlHashUtil.getGlobalHashDefinitions(getProject(), getCanonicalName())) {
if (!variable.equals(parent)) {
result.add(variable);
}
}
}
return result;
}
Aggregations