summaryrefslogtreecommitdiff
path: root/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java
diff options
context:
space:
mode:
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.java149
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;
+ }
+ }
+}