diff options
Diffstat (limited to 'platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java')
-rw-r--r-- | platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java new file mode 100644 index 000000000000..99de432f101d --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java @@ -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 myIndentToUsagesMap = 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(myIndentToUsagesMap); + 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 = myIndentToUsagesMap.get(relativeIndent); + myIndentToUsagesMap.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 myIndentToUsagesMap.get(indent); + } + + @Override + public int getTotalIndentSizesDetected() { + return myIndentToUsagesMap.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; + } + } +} |