diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java index 86b6bd982fbc..69118990a54a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java @@ -22,6 +22,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; +import com.intellij.util.TripleFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,6 +35,8 @@ public final class CompilerMessageImpl implements CompilerMessage { private final VirtualFile myFile; private final int myRow; private final int myColumn; + @NotNull + private TripleFunction myColumnAdjuster = (msg, line, col) -> col; public CompilerMessageImpl(Project project, CompilerMessageCategory category, String message) { this(project, category, message, null, -1, -1, null); @@ -55,6 +58,10 @@ public final class CompilerMessageImpl implements CompilerMessage { myFile = file; } + public void setColumnAdjuster(@NotNull TripleFunction columnAdjuster) { + myColumnAdjuster = columnAdjuster; + } + @NotNull @Override public CompilerMessageCategory getCategory() { @@ -75,7 +82,7 @@ public final class CompilerMessageImpl implements CompilerMessage { if (virtualFile != null && virtualFile.isValid()) { final int line = getLine() - 1; // editor lines are zero-based if (line >= 0) { - return myNavigatable = new OpenFileDescriptor(myProject, virtualFile, line, Math.max(0, getColumn()-1)); + return myNavigatable = new OpenFileDescriptor(myProject, virtualFile, line, myColumnAdjuster.fun(this, line, Math.max(0, getColumn()-1))) ; } } return null; diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java b/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java index 66fc6e1cdefa..76c4381fa5b0 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java @@ -15,10 +15,16 @@ */ package com.intellij.compiler.impl; +import com.intellij.codeStyle.CodeStyleFacade; import com.intellij.compiler.CompilerMessageImpl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompilerMessage; import com.intellij.openapi.compiler.CompilerMessageCategory; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.pom.Navigatable; @@ -32,11 +38,15 @@ import java.util.*; * Date: 27-Jan-16 */ public class MessagesContainer { + + private static final int JAVAC_TAB_SIZE = 8; private final Project myProject; private final Map> myMessages = new EnumMap<>(CompilerMessageCategory.class); + private final int myTabSize; public MessagesContainer(Project project) { myProject = project; + myTabSize = CodeStyleFacade.getInstance().getTabSize(StdFileTypes.JAVA); } @NotNull @@ -52,11 +62,48 @@ public class MessagesContainer { public CompilerMessage addMessage(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum, Navigatable navigatable) { CompilerMessageImpl msg = new CompilerMessageImpl(myProject, category, message, findFileByUrl(url), lineNum, columnNum, navigatable); if (addMessage(msg)) { + msg.setColumnAdjuster((m, line, col) -> adjustColumn(m, line, col)); return msg; } return null; } + private int adjustColumn(final CompilerMessage m, final int line, final int col) { + if (myTabSize != JAVAC_TAB_SIZE && line >= 1) { + // javac uses hard-coded tab size 8 chars. So recalculate only if project's codestyle is different + final VirtualFile file = m.getVirtualFile(); + if (file != null && file.isValid()) { + final Document doc = FileDocumentManager.getInstance().getDocument(file); + if (doc != null) { + final int tabCount = ApplicationManager.getApplication().runReadAction((Computable)() -> { + final CharSequence seq = doc.getCharsSequence(); + int tcount = 0; + final int start = doc.getLineStartOffset(line); + final int end = doc.getLineEndOffset(line); + int charsExpanded = 0; + for (int i = start; i< end; i++) { + if (seq.charAt(i) == '\t') { + charsExpanded += JAVAC_TAB_SIZE; + tcount++; + } + else { + charsExpanded += 1; + } + if (charsExpanded >= col) { + break; // consider only those tabs that are located before the given column number + } + } + return tcount; + }); + if (tabCount > 0) { + return Math.max(0, col + tabCount * (myTabSize - JAVAC_TAB_SIZE)); + } + } + } + } + return col; + } + public boolean addMessage(CompilerMessage msg) { Collection messages = myMessages.computeIfAbsent(msg.getCategory(), k -> new LinkedHashSet<>()); return messages.add(msg);