Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve logging for CallDefinitionClause.renderElement #609

Merged
merged 10 commits into from Feb 10, 2017

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions .travis.yml
Expand Up @@ -68,9 +68,9 @@ before_install:
- tar xvfz jdk-8u112-linux-x64.tar.gz
- export JAVA_HOME=${PWD}/jdk1.8.0_112
- export PATH=${JAVA_HOME}/bin:${PATH}
- wget http://www-us.apache.org/dist//ant/binaries/apache-ant-1.10.0-bin.tar.gz
- tar xvfz apache-ant-1.10.0-bin.tar.gz
- export PATH=${PWD}/apache-ant-1.10.0/bin:${PATH}
- wget http://www-us.apache.org/dist//ant/binaries/apache-ant-1.10.1-bin.tar.gz
- tar xvfz apache-ant-1.10.1-bin.tar.gz
- export PATH=${PWD}/apache-ant-1.10.1/bin:${PATH}
- java -version
- ant -version
install:
Expand Down
11 changes: 10 additions & 1 deletion src/org/elixir_lang/annonator/Callable.java
Expand Up @@ -11,6 +11,7 @@
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import org.elixir_lang.ElixirSyntaxHighlighter;
import org.elixir_lang.errorreport.Logger;
import org.elixir_lang.psi.call.Call;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -66,7 +67,15 @@ private void visitCall(@NotNull final Call call) {
if (reference instanceof PsiPolyVariantReference) {
PsiPolyVariantReference polyVariantReference = (PsiPolyVariantReference) reference;

ResolveResult[] resolveResults = polyVariantReference.multiResolve(false);
ResolveResult[] resolveResults;

try {
resolveResults = polyVariantReference.multiResolve(false);
} catch (StackOverflowError stackOverflowError) {
Logger.error(Callable.class, "StackOverflowError when annotating Call", call);
resolveResults = new ResolveResult[0];
}

List<ResolveResult> validResolveResults = ContainerUtil.filter(
resolveResults,
new Condition<ResolveResult>() {
Expand Down
12 changes: 9 additions & 3 deletions src/org/elixir_lang/annonator/ModuleAttribute.java
Expand Up @@ -32,6 +32,7 @@
import static org.elixir_lang.psi.impl.ElixirPsiImplUtil.identifierName;
import static org.elixir_lang.psi.impl.ElixirPsiImplUtil.stripAccessExpression;
import static org.elixir_lang.reference.ModuleAttribute.*;
import static org.elixir_lang.structure_view.element.CallDefinitionHead.stripAllOuterParentheses;

/**
* Annotates module attributes.
Expand Down Expand Up @@ -578,9 +579,14 @@ private void highlightSpecification(AtUnqualifiedNoParenthesesCall atUnqualified
if (leftOperand instanceof Type) {
Type typeOperation = (Type) leftOperand;
PsiElement typeOperationLeftOperand = typeOperation.leftOperand();
PsiElement strippedTypeOperationLeftOperand = null;

if (typeOperationLeftOperand instanceof Call) {
Call call = (Call) typeOperationLeftOperand;
if (typeOperationLeftOperand != null) {
strippedTypeOperationLeftOperand = stripAllOuterParentheses(typeOperationLeftOperand);
}

if (strippedTypeOperationLeftOperand instanceof Call) {
Call call = (Call) strippedTypeOperationLeftOperand;
PsiElement functionNameElement = call.functionNameElement();

if (functionNameElement != null) {
Expand Down Expand Up @@ -613,7 +619,7 @@ private void highlightSpecification(AtUnqualifiedNoParenthesesCall atUnqualified
);
}
} else {
cannotHighlightTypes(typeOperationLeftOperand);
cannotHighlightTypes(strippedTypeOperationLeftOperand);
}

PsiElement matchedTypeOperationRightOperand = typeOperation.rightOperand();
Expand Down
@@ -1,10 +1,13 @@
package org.elixir_lang.code_insight.lookup.element_renderer;

import com.google.common.base.Joiner;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.diagnostic.LogMessageEx;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import org.elixir_lang.errorreport.Logger;
import org.elixir_lang.psi.call.Call;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -35,37 +38,98 @@ public void renderElement(LookupElement element, LookupElementPresentation prese

PsiElement psiElement = element.getPsiElement();

assert psiElement != null;

if (psiElement instanceof Call) {
Call call = (Call) psiElement;
if (psiElement == null) {
renderObject(element);
} else {
renderPsiElement(psiElement, presentation);
}
}

if (org.elixir_lang.structure_view.element.CallDefinitionClause.is(call)) {
org.elixir_lang.structure_view.element.CallDefinitionClause structureView =
org.elixir_lang.structure_view.element.CallDefinitionClause.fromCall(call);
/*
* Private Instance Methods
*/

if (structureView != null) {
ItemPresentation structureViewPresentation = structureView.getPresentation();
private void renderCall(@NotNull Call call, @NotNull LookupElementPresentation presentation) {
if (org.elixir_lang.structure_view.element.CallDefinitionClause.is(call)) {
renderCallDefinitionClause(call, presentation);
}
}

presentation.setIcon(structureViewPresentation.getIcon(true));
String presentableText = structureViewPresentation.getPresentableText();
private void renderCallDefinitionClause(@NotNull Call call, @NotNull LookupElementPresentation presentation) {
org.elixir_lang.structure_view.element.CallDefinitionClause structureView =
org.elixir_lang.structure_view.element.CallDefinitionClause.fromCall(call);

if (presentableText != null) {
int nameLength = name.length();
int presentableTextLength = presentableText.length();
if (structureView != null) {
renderStructureView(structureView, presentation);
}
}

if (nameLength <= presentableTextLength) {
presentation.appendTailText(presentableText.substring(nameLength), true);
}
}
private void renderItemPresentation(@NotNull ItemPresentation itemPresentation,
@NotNull LookupElementPresentation lookupElementPresentation) {
lookupElementPresentation.setIcon(itemPresentation.getIcon(true));
String presentableText = itemPresentation.getPresentableText();

String locationString = structureViewPresentation.getLocationString();
if (presentableText != null) {
int nameLength = name.length();
int presentableTextLength = presentableText.length();

if (locationString != null) {
presentation.appendTailText(" (" + locationString + ")", false);
}
}
if (nameLength <= presentableTextLength) {
lookupElementPresentation.appendTailText(presentableText.substring(nameLength), true);
}
}

String locationString = itemPresentation.getLocationString();

if (locationString != null) {
lookupElementPresentation.appendTailText(" (" + locationString + ")", false);
}
}

private void renderObject(@NotNull LookupElement lookupElement) {
Logger logger = Logger.getInstance(CallDefinitionClause.class);
Object object = lookupElement.getObject();
String userMessage = "CallDefinitionClause render called on LookupElement with null getPsiElement\n" +
"## name\n" +
"\n" +
"```\n" +
name + "\n" +
"```\n" +
"\n" +
"## getObject()\n"+
"\n" +
"### toString()\n" +
"\n" +
"```\n" +
object.toString() + "\n" +
"```\n" +
"\n" +
"### getClass().getName()\n" +
"\n" +
"```\n" +
object.getClass().getName() + "\n" +
"```\n";

String details = Joiner.on("\n").join(new Throwable().getStackTrace());
String title = "CallDefinitionClause render called on LookupElement with null getPsiElement";
logger.error(
LogMessageEx.createEvent(
userMessage,
details,
title,
null,
(Attachment) null
)
);
}

private void renderPsiElement(@NotNull PsiElement psiElement, @NotNull LookupElementPresentation presentation) {
if (psiElement instanceof Call) {
renderCall((Call) psiElement, presentation);
}
}

private void renderStructureView(@NotNull org.elixir_lang.structure_view.element.CallDefinitionClause structureView,
@NotNull LookupElementPresentation presentation) {
renderItemPresentation(structureView.getPresentation(), presentation);
}
}
8 changes: 8 additions & 0 deletions src/org/elixir_lang/errorreport/Logger.java
Expand Up @@ -112,6 +112,14 @@ private static String excerpt(@NotNull PsiFile containingFile, @NotNull PsiEleme
excerptBuilder.append(startingLine);
excerptBuilder.append('-');
excerptBuilder.append(endingLine);

VirtualFile virtualFile = containingFile.getVirtualFile();

if (virtualFile != null) {
excerptBuilder.append(" in ");
excerptBuilder.append(virtualFile.getPath());
}

excerptBuilder.append("\n");
}

Expand Down
9 changes: 8 additions & 1 deletion src/org/elixir_lang/psi/Import.java
Expand Up @@ -60,7 +60,14 @@ public Boolean fun(@NotNull @SuppressWarnings("unused") Call call) {
*/
public static void callDefinitionClauseCallWhile(@NotNull Call importCall,
@NotNull final Function<Call, Boolean> function) {
Call modularCall = modular(importCall);
Call modularCall;

try {
modularCall = modular(importCall);
} catch (StackOverflowError stackOverflowError) {
Logger.error(Import.class, "StackvoerflowError while finding modular for import", importCall);
modularCall = null;
}

if (modularCall != null) {
final Function<Call, Boolean> optionsFilter = callDefinitionClauseCallFilter(importCall);
Expand Down
30 changes: 26 additions & 4 deletions src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java
Expand Up @@ -4907,6 +4907,25 @@ public static OtpErlangObject quotedVariable(@NotNull final OtpErlangObject quot
);
}

@Contract(pure = true)
@NotNull
public static boolean recursiveKernelImport(@NotNull QualifiableAlias qualifiableAlias,
@NotNull PsiElement maxScope) {
boolean recursiveKernelImport = false;

if (maxScope instanceof ElixirFile) {
ElixirFile elixirFile = (ElixirFile) maxScope;

if (elixirFile.getName().equals("kernel.ex")) {
String qualifiableAliasName = qualifiableAlias.getName();

recursiveKernelImport = qualifiableAliasName != null && qualifiableAliasName.equals(KERNEL);
}
}

return recursiveKernelImport;
}

@Contract(pure = true)
@NotNull
public static int resolvedFinalArity(@NotNull final Call call) {
Expand Down Expand Up @@ -5631,10 +5650,13 @@ public static Call maybeAliasToModular(@NotNull final PsiElement maybeAlias, @No

if (maybeQualifiableAlias instanceof QualifiableAlias) {
QualifiableAlias qualifiableAlias = (QualifiableAlias) maybeQualifiableAlias;
/* need to construct reference directly as qualified aliases don't return a
reference except for the outermost */
PsiPolyVariantReference reference = new org.elixir_lang.reference.Module(qualifiableAlias, maxScope);
modular = aliasToModular(qualifiableAlias, reference);

if (!recursiveKernelImport(qualifiableAlias, maxScope)) {
/* need to construct reference directly as qualified aliases don't return a reference except for the
outermost */
PsiPolyVariantReference reference = new org.elixir_lang.reference.Module(qualifiableAlias, maxScope);
modular = aliasToModular(qualifiableAlias, reference);
}
}

return modular;
Expand Down
21 changes: 13 additions & 8 deletions src/org/elixir_lang/psi/scope/CallDefinitionClause.java
Expand Up @@ -5,6 +5,7 @@
import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.Function;
import org.elixir_lang.errorreport.Logger;
import org.elixir_lang.psi.Import;
import org.elixir_lang.psi.call.Call;
import org.elixir_lang.structure_view.element.modular.Module;
Expand Down Expand Up @@ -80,15 +81,19 @@ protected boolean execute(@NotNull Call element, @NotNull final ResolveState sta
} else if (Import.is(element)) {
final ResolveState importState = state.put(IMPORT_CALL, element);

Import.callDefinitionClauseCallWhile(
element,
new Function<Call,Boolean>() {
@Override
public Boolean fun(Call callDefinitionClause) {
return executeOnCallDefinitionClause(callDefinitionClause, importState);
try {
Import.callDefinitionClauseCallWhile(
element,
new Function<Call, Boolean>() {
@Override
public Boolean fun(Call callDefinitionClause) {
return executeOnCallDefinitionClause(callDefinitionClause, importState);
}
}
}
);
);
} catch (StackOverflowError stackOverflowError) {
Logger.error(CallDefinitionClause.class, "StackOverflowError while processing import", element);
}
} else if (Module.is(element)) {
Call[] childCalls = macroChildCalls(element);

Expand Down
24 changes: 17 additions & 7 deletions src/org/elixir_lang/psi/scope/module/MultiResolve.java
@@ -1,5 +1,6 @@
package org.elixir_lang.psi.scope.module;

import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
Expand All @@ -15,6 +16,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static org.elixir_lang.Module.concat;
Expand Down Expand Up @@ -42,13 +44,21 @@ public static List<ResolveResult> resolveResultList(@NotNull String name,
private static Collection<NamedElement> indexedNamedElements(@NotNull PsiNamedElement match,
@NotNull String unaliasedName) {
Project project = match.getProject();
return StubIndex.getElements(
AllName.KEY,
unaliasedName,
project,
GlobalSearchScope.allScope(project),
NamedElement.class
);
Collection<NamedElement> indexNamedElementCollection;

if (DumbService.isDumb(project)) {
indexNamedElementCollection = Collections.emptyList();
} else {
indexNamedElementCollection = StubIndex.getElements(
AllName.KEY,
unaliasedName,
project,
GlobalSearchScope.allScope(project),
NamedElement.class
);
}

return indexNamedElementCollection;
}

@Nullable
Expand Down