Skip to content

Commit

Permalink
#452: introduce method separators
Browse files Browse the repository at this point in the history
  • Loading branch information
deadok22 committed Mar 24, 2014
1 parent 043718b commit 9bef902
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@

<codeInsight.lineMarkerProvider language="Erlang" implementationClass="org.intellij.erlang.marker.ErlangRecursiveCallLineMarkerProvider"/>
<codeInsight.lineMarkerProvider language="Erlang" implementationClass="org.intellij.erlang.marker.ErlangBehaviourMarkerProvider"/>
<codeInsight.lineMarkerProvider language="Erlang" implementationClass="org.intellij.erlang.marker.ErlangMethodSeparatorProvider"/>

<codeInsight.parameterInfo language="Erlang" implementationClass="org.intellij.erlang.ErlangParameterInfoHandler"/>
<codeInsight.gotoSuper language="Erlang" implementationClass="org.intellij.erlang.navigation.ErlangGotoSuperHandler"/>
Expand Down
82 changes: 82 additions & 0 deletions src/org/intellij/erlang/marker/ErlangMethodSeparatorProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2012-2014 Sergey Ignatov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.intellij.erlang.marker;

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.daemon.impl.LineMarkersPass;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.erlang.psi.*;
import org.intellij.erlang.psi.impl.ErlangPsiImplUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.List;

public class ErlangMethodSeparatorProvider implements LineMarkerProvider {
private final DaemonCodeAnalyzerSettings myDaemonSettings;
private final EditorColorsManager myColorsManager;

public ErlangMethodSeparatorProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) {
myDaemonSettings = daemonSettings;
myColorsManager = colorsManager;
}

@Nullable
@Override
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement function) {
if (myDaemonSettings.SHOW_METHOD_SEPARATORS && function instanceof ErlangFunction) {
PsiElement anchor = findAnchorElementForMethodSeparator((ErlangFunction) function);
return LineMarkersPass.createMethodSeparatorLineMarker(anchor, myColorsManager);
}
return null;
}

@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) {
}

private static PsiElement findAnchorElementForMethodSeparator(ErlangFunction function) {
ErlangAttribute specAttribute = getSpecAttributeForFunction(function);
PsiElement leftmostPossibleAnchor = function;
PsiElement leftmostElement = function;
while ((leftmostElement = leftmostElement.getPrevSibling()) != null) {
if (leftmostElement instanceof PsiComment || leftmostElement == specAttribute) {
leftmostPossibleAnchor = leftmostElement;
}
else if (!(leftmostElement instanceof PsiWhiteSpace)) break;
}
return leftmostPossibleAnchor;
}

@Nullable
private static ErlangAttribute getSpecAttributeForFunction(ErlangFunction function) {
ErlangSpecification spec = ErlangPsiImplUtil.getSpecification(function);
ErlangFunTypeSigs signature = ErlangPsiImplUtil.getSignature(spec);
ErlangSpecFun specFun = signature != null ? signature.getSpecFun() : null;
PsiReference reference = specFun != null ? specFun.getReference() : null;
boolean isSpecForPassedFunction = reference != null && reference.isReferenceTo(function);
return isSpecForPassedFunction ? PsiTreeUtil.getParentOfType(spec, ErlangAttribute.class) : null;
}
}
3 changes: 3 additions & 0 deletions testData/marker/methodSeparators/comment.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
% comment
foo() ->
ok.
4 changes: 4 additions & 0 deletions testData/marker/methodSeparators/commentAndSpec.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
% comment
-spec foo() -> ok.
foo() ->
ok.
5 changes: 5 additions & 0 deletions testData/marker/methodSeparators/commentSpecAndComment.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
% comment
-spec foo() -> ok.
% comment
foo() ->
ok.
2 changes: 2 additions & 0 deletions testData/marker/methodSeparators/function.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
foo() ->
ok.
3 changes: 3 additions & 0 deletions testData/marker/methodSeparators/spec.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-spec foo() -> ok.
foo() ->
ok.
4 changes: 4 additions & 0 deletions testData/marker/methodSeparators/specAndComment.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-spec foo() -> ok.
% comment
foo() ->
ok.
3 changes: 3 additions & 0 deletions testData/marker/methodSeparators/specOfOtherFunction.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-spec bar() -> ok.
foo() ->
ok.
5 changes: 5 additions & 0 deletions testData/marker/methodSeparators/twoFunctions.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
foo() ->
ok.

bar() ->
ok.
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2012-2014 Sergey Ignatov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.intellij.erlang.marker;

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import org.intellij.erlang.utils.ErlangLightPlatformCodeInsightFixtureTestCase;

import java.util.List;

public class ErlangMethodSeparatorProviderTest extends ErlangLightPlatformCodeInsightFixtureTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
setShowMethodSeparatorsEnabled(true);
}

@Override
protected void tearDown() throws Exception {
super.tearDown();
setShowMethodSeparatorsEnabled(false);
}

@Override
protected String getTestDataPath() {
return "testData/marker/methodSeparators/";
}

@Override
protected boolean isWriteActionRequired() {
return false;
}

private static void setShowMethodSeparatorsEnabled(boolean b) {
DaemonCodeAnalyzerSettings settings = DaemonCodeAnalyzerSettings.getInstance();
settings.SHOW_METHOD_SEPARATORS = b;
}

protected void doTest(Integer ... expectedLineMarkers) {
myFixture.configureByFile(getTestName(true) + ".erl");
myFixture.doHighlighting();
assertSameElements(getMarkedLineNumbers(), expectedLineMarkers);
}

private Integer[] getMarkedLineNumbers() {
List<LineMarkerInfo> lineMarkers = DaemonCodeAnalyzerImpl.getLineMarkers(myFixture.getEditor().getDocument(), myFixture.getProject());
assertNotNull(lineMarkers);
Integer[] markedLineNumbers = new Integer[lineMarkers.size()];
for (int i = 0; i < lineMarkers.size(); i++) {
markedLineNumbers[i] = myFixture.getEditor().getDocument().getLineNumber(lineMarkers.get(i).startOffset);
}
return markedLineNumbers;
}

public void testFunction() throws Exception { doTest(0); }
public void testTwoFunctions() throws Exception { doTest(0, 3); }
public void testSpec() throws Exception { doTest(0); }
public void testComment() throws Exception { doTest(0); }
public void testSpecAndComment() throws Exception { doTest(0); }
public void testCommentAndSpec() throws Exception { doTest(0); }
public void testCommentSpecAndComment() throws Exception { doTest(0); }
public void testSpecOfOtherFunction() throws Exception { doTest(1); }
}

0 comments on commit 9bef902

Please sign in to comment.