mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
extracted interface, eliminated possible exceptions due to small indent size diversity
This commit is contained in:
+15
-9
@@ -50,7 +50,7 @@ public class IndentOptionsDetector {
|
||||
|
||||
if (myDocument != null) {
|
||||
List<LineIndentInfo> linesInfo = new LineIndentInfoBuilder(myDocument.getCharsSequence()).build();
|
||||
IndentUsageStatistics stats = new IndentUsageStatistics(linesInfo);
|
||||
IndentUsageStatistics stats = new IndentUsageStatisticsImpl(linesInfo);
|
||||
adjustIndentOptions(indentOptions, stats);
|
||||
}
|
||||
|
||||
@@ -80,18 +80,24 @@ public class IndentOptionsDetector {
|
||||
}
|
||||
|
||||
private static int getPositiveIndentSize(@NotNull IndentUsageStatistics stats) {
|
||||
IndentUsageInfo maxUsedIndentInfo = stats.getMaxUsedIndentInfo(0);
|
||||
int maxIndentSize = maxUsedIndentInfo.getIndentSize();
|
||||
if (maxIndentSize == 0) {
|
||||
maxUsedIndentInfo = stats.getMaxUsedIndentInfo(1);
|
||||
maxIndentSize = maxUsedIndentInfo.getIndentSize();
|
||||
int totalIndentSizesDetected = stats.getTotalIndentSizesDetected();
|
||||
if (totalIndentSizesDetected == 0) return -1;
|
||||
|
||||
IndentUsageInfo maxUsedIndentInfo = stats.getKMostUsedIndentInfo(0);
|
||||
int maxUsedIndentSize = maxUsedIndentInfo.getIndentSize();
|
||||
|
||||
if (maxUsedIndentSize == 0) {
|
||||
if (totalIndentSizesDetected < 1) return -1;
|
||||
|
||||
maxUsedIndentInfo = stats.getKMostUsedIndentInfo(1);
|
||||
maxUsedIndentSize = maxUsedIndentInfo.getIndentSize();
|
||||
}
|
||||
|
||||
if (maxIndentSize <= MAX_INDENT_TO_DETECT) {
|
||||
int totalUsagesWithoutZeroIndent = stats.getTotalLinesWithLeadingSpaces() - stats.getTimesUsedIndent(0);
|
||||
if (maxUsedIndentSize <= MAX_INDENT_TO_DETECT) {
|
||||
int totalUsagesWithoutZeroIndent = stats.getTotalLinesWithLeadingSpaces() - stats.getTimesIndentUsed(0);
|
||||
double usageRate = (double)maxUsedIndentInfo.getTimesUsed() / totalUsagesWithoutZeroIndent;
|
||||
if (usageRate > RATE_THRESHOLD) {
|
||||
return maxIndentSize;
|
||||
return maxUsedIndentSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-116
@@ -15,126 +15,16 @@
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.autodetect;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import gnu.trove.TIntIntIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
public interface IndentUsageStatistics {
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
int getTotalLinesWithLeadingTabs();
|
||||
|
||||
public class IndentUsageStatistics {
|
||||
private static final Comparator<IndentUsageInfo> DECREASING_ORDER = new Comparator<IndentUsageInfo>() {
|
||||
@Override
|
||||
public int compare(@NotNull IndentUsageInfo o1, @NotNull IndentUsageInfo o2) {
|
||||
return o1.getTimesUsed() < o2.getTimesUsed() ? 1 : o1.getTimesUsed() == o2.getTimesUsed() ? 0 : -1;
|
||||
}
|
||||
};
|
||||
int getTotalLinesWithLeadingSpaces();
|
||||
|
||||
private List<LineIndentInfo> myLineInfos;
|
||||
IndentUsageInfo getKMostUsedIndentInfo(int k);
|
||||
|
||||
private int myPreviousLineIndent;
|
||||
private int myPreviousRelativeIndent;
|
||||
int getTotalIndentSizesDetected();
|
||||
|
||||
private int myTotalLinesWithTabs = 0;
|
||||
private int myTotalLinesWithWhiteSpaces = 0;
|
||||
int getTimesIndentUsed(int indent);
|
||||
|
||||
private TIntIntHashMap myIndentToUsages = new TIntIntHashMap();
|
||||
private List<IndentUsageInfo> myIndentUsages = ContainerUtil.newArrayList();
|
||||
private Stack<IndentData> myParentIndents = ContainerUtil.newStack(new IndentData(0, 0));
|
||||
|
||||
public IndentUsageStatistics(@NotNull List<LineIndentInfo> lineInfos) {
|
||||
myLineInfos = lineInfos;
|
||||
buildIndentToUsagesMap();
|
||||
myIndentUsages = toIndentUsageList(myIndentToUsages);
|
||||
ContainerUtil.sort(myIndentUsages, DECREASING_ORDER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<IndentUsageInfo> toIndentUsageList(@NotNull TIntIntHashMap indentToUsages) {
|
||||
List<IndentUsageInfo> indentUsageInfos = ContainerUtil.newArrayList();
|
||||
TIntIntIterator it = indentToUsages.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.advance();
|
||||
indentUsageInfos.add(new IndentUsageInfo(it.key(), it.value()));
|
||||
}
|
||||
return indentUsageInfos;
|
||||
}
|
||||
|
||||
public void buildIndentToUsagesMap() {
|
||||
myPreviousLineIndent = 0;
|
||||
myPreviousRelativeIndent = 0;
|
||||
|
||||
for (LineIndentInfo lineInfo : myLineInfos) {
|
||||
if (lineInfo.isLineWithTabs()) {
|
||||
myTotalLinesWithTabs++;
|
||||
}
|
||||
else if (lineInfo.isLineWithWhiteSpaceIndent()) {
|
||||
handleWhiteSpaceIndent(lineInfo.getIndentSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private IndentData findParentIndent(int indent) {
|
||||
while (myParentIndents.size() != 1 && myParentIndents.peek().indent > indent) {
|
||||
myParentIndents.pop();
|
||||
}
|
||||
return myParentIndents.peek();
|
||||
}
|
||||
|
||||
private void handleWhiteSpaceIndent(int currentIndent) {
|
||||
int relativeIndent = currentIndent - myPreviousLineIndent;
|
||||
if (relativeIndent < 0) {
|
||||
IndentData indentData = findParentIndent(currentIndent);
|
||||
myPreviousLineIndent = indentData.indent;
|
||||
myPreviousRelativeIndent = indentData.relativeIndent;
|
||||
relativeIndent = currentIndent - myPreviousLineIndent;
|
||||
}
|
||||
|
||||
if (relativeIndent == 0) {
|
||||
relativeIndent = myPreviousRelativeIndent;
|
||||
}
|
||||
else {
|
||||
myParentIndents.push(new IndentData(currentIndent, relativeIndent));
|
||||
}
|
||||
|
||||
increaseIndentUsage(relativeIndent);
|
||||
|
||||
myPreviousRelativeIndent = relativeIndent;
|
||||
myPreviousLineIndent = currentIndent;
|
||||
myTotalLinesWithWhiteSpaces++;
|
||||
}
|
||||
|
||||
private void increaseIndentUsage(int relativeIndent) {
|
||||
int timesUsed = myIndentToUsages.get(relativeIndent);
|
||||
myIndentToUsages.put(relativeIndent, ++timesUsed);
|
||||
}
|
||||
|
||||
public int getTotalLinesWithLeadingTabs() {
|
||||
return myTotalLinesWithTabs;
|
||||
}
|
||||
|
||||
public int getTotalLinesWithLeadingSpaces() {
|
||||
return myTotalLinesWithWhiteSpaces;
|
||||
}
|
||||
|
||||
public IndentUsageInfo getMaxUsedIndentInfo(int rank) {
|
||||
return myIndentUsages.get(rank);
|
||||
}
|
||||
|
||||
public int getTimesUsedIndent(int indent) {
|
||||
return myIndentToUsages.get(indent);
|
||||
}
|
||||
|
||||
private static class IndentData {
|
||||
public final int indent;
|
||||
public final int relativeIndent;
|
||||
|
||||
public IndentData(int indent, int relativeIndent) {
|
||||
this.indent = indent;
|
||||
this.relativeIndent = relativeIndent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* 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 com.intellij.psi.codeStyle.autodetect;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import gnu.trove.TIntIntIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class IndentUsageStatisticsImpl implements IndentUsageStatistics {
|
||||
private static final Comparator<IndentUsageInfo> DECREASING_ORDER = new Comparator<IndentUsageInfo>() {
|
||||
@Override
|
||||
public int compare(@NotNull IndentUsageInfo o1, @NotNull IndentUsageInfo o2) {
|
||||
return o1.getTimesUsed() < o2.getTimesUsed() ? 1 : o1.getTimesUsed() == o2.getTimesUsed() ? 0 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
private List<LineIndentInfo> myLineInfos;
|
||||
|
||||
private int myPreviousLineIndent;
|
||||
private int myPreviousRelativeIndent;
|
||||
|
||||
private int myTotalLinesWithTabs = 0;
|
||||
private int myTotalLinesWithWhiteSpaces = 0;
|
||||
|
||||
private TIntIntHashMap myIndentToUsages = new TIntIntHashMap();
|
||||
private List<IndentUsageInfo> myIndentUsages = ContainerUtil.newArrayList();
|
||||
private Stack<IndentData> myParentIndents = ContainerUtil.newStack(new IndentData(0, 0));
|
||||
|
||||
public IndentUsageStatisticsImpl(@NotNull List<LineIndentInfo> lineInfos) {
|
||||
myLineInfos = lineInfos;
|
||||
buildIndentToUsagesMap();
|
||||
myIndentUsages = toIndentUsageList(myIndentToUsages);
|
||||
ContainerUtil.sort(myIndentUsages, DECREASING_ORDER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<IndentUsageInfo> toIndentUsageList(@NotNull TIntIntHashMap indentToUsages) {
|
||||
List<IndentUsageInfo> indentUsageInfos = ContainerUtil.newArrayList();
|
||||
TIntIntIterator it = indentToUsages.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.advance();
|
||||
indentUsageInfos.add(new IndentUsageInfo(it.key(), it.value()));
|
||||
}
|
||||
return indentUsageInfos;
|
||||
}
|
||||
|
||||
public void buildIndentToUsagesMap() {
|
||||
myPreviousLineIndent = 0;
|
||||
myPreviousRelativeIndent = 0;
|
||||
|
||||
for (LineIndentInfo lineInfo : myLineInfos) {
|
||||
if (lineInfo.isLineWithTabs()) {
|
||||
myTotalLinesWithTabs++;
|
||||
}
|
||||
else if (lineInfo.isLineWithWhiteSpaceIndent()) {
|
||||
handleWhiteSpaceIndent(lineInfo.getIndentSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private IndentData findParentIndent(int indent) {
|
||||
while (myParentIndents.size() != 1 && myParentIndents.peek().indent > indent) {
|
||||
myParentIndents.pop();
|
||||
}
|
||||
return myParentIndents.peek();
|
||||
}
|
||||
|
||||
private void handleWhiteSpaceIndent(int currentIndent) {
|
||||
int relativeIndent = currentIndent - myPreviousLineIndent;
|
||||
if (relativeIndent < 0) {
|
||||
IndentData indentData = findParentIndent(currentIndent);
|
||||
myPreviousLineIndent = indentData.indent;
|
||||
myPreviousRelativeIndent = indentData.relativeIndent;
|
||||
relativeIndent = currentIndent - myPreviousLineIndent;
|
||||
}
|
||||
|
||||
if (relativeIndent == 0) {
|
||||
relativeIndent = myPreviousRelativeIndent;
|
||||
}
|
||||
else {
|
||||
myParentIndents.push(new IndentData(currentIndent, relativeIndent));
|
||||
}
|
||||
|
||||
increaseIndentUsage(relativeIndent);
|
||||
|
||||
myPreviousRelativeIndent = relativeIndent;
|
||||
myPreviousLineIndent = currentIndent;
|
||||
myTotalLinesWithWhiteSpaces++;
|
||||
}
|
||||
|
||||
private void increaseIndentUsage(int relativeIndent) {
|
||||
int timesUsed = myIndentToUsages.get(relativeIndent);
|
||||
myIndentToUsages.put(relativeIndent, ++timesUsed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalLinesWithLeadingTabs() {
|
||||
return myTotalLinesWithTabs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalLinesWithLeadingSpaces() {
|
||||
return myTotalLinesWithWhiteSpaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndentUsageInfo getKMostUsedIndentInfo(int k) {
|
||||
return myIndentUsages.get(k);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimesIndentUsed(int indent) {
|
||||
return myIndentToUsages.get(indent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalIndentSizesDetected() {
|
||||
return myIndentToUsages.size();
|
||||
}
|
||||
|
||||
private static class IndentData {
|
||||
public final int indent;
|
||||
public final int relativeIndent;
|
||||
|
||||
public IndentData(int indent, int relativeIndent) {
|
||||
this.indent = indent;
|
||||
this.relativeIndent = relativeIndent;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -112,8 +112,8 @@ public class IndentAutoDetectionTest extends LightPlatformCodeInsightTestCase {
|
||||
configureByFile(getTestName(true) + ".java");
|
||||
Document document = getDocument(myFile);
|
||||
List<LineIndentInfo> lines = new LineIndentInfoBuilder(document.getCharsSequence()).build();
|
||||
IndentUsageStatistics statistics = new IndentUsageStatistics(lines);
|
||||
return statistics.getMaxUsedIndentInfo(0);
|
||||
IndentUsageStatistics statistics = new IndentUsageStatisticsImpl(lines);
|
||||
return statistics.getKMostUsedIndentInfo(0);
|
||||
}
|
||||
|
||||
private static void doTestLineToIndentMapping(@NotNull CharSequence text, int... spacesForLine) {
|
||||
|
||||
Reference in New Issue
Block a user