Merge remote-tracking branch 'origin/master'

This commit is contained in:
Andrey Vlasovskikh
2015-02-17 16:47:11 +03:00
14 changed files with 110 additions and 193 deletions
@@ -21,8 +21,6 @@ import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
import com.intellij.util.ArrayUtilRt
import org.jetbrains.annotations.NotNull
import static junit.framework.Assert.assertNotNull
/**
* @author Denis Zhdanov
* @since 2/7/13 4:01 PM
@@ -53,21 +51,20 @@ class Test {
)
}
void "test that inner comment indents do not exceed"() {
// IDEA-89471.
void "test no indent guides in commented regions"() {
doTest(
"""\
class Test {
void test() {
| return;
//| | if (true) {
//| | | int i1 = 1;
//| | | int i2 = 2;
//| | | if (true) {
//| | | | int j1 = 1;
//| | | | int j2 = 2;
//| | | }
//| | }
//| if (true) {
//| int i1 = 1;
//| int i2 = 2;
//| if (true) {
//| int j1 = 1;
//| int j2 = 2;
//| }
//| }
//| int k = 1;
}
}
@@ -76,13 +73,12 @@ class Test {
}
void "test indent guide which starts on comment line"() {
// IDEA-62184
doTest(
"""\
class Test {
void test(int i) {
| switch (i) {
| //
| |//
| | case 1:
| | case 2:
| }
@@ -125,10 +121,10 @@ class Test {
class Test {
int test() {
| return 1 /*{
| | int test2() {
| | | int i1;
| | }
| | int i2;
| int test2() {
| int i1;
| }
| int i2;
| }*/;
}
}
@@ -136,6 +132,21 @@ class Test {
)
}
void "test empty comment does not break indents"() {
doTest(
"""\
class Test {
void m() {
|
//|
|
| int v;
}
}
"""
)
}
private void doTest(@NotNull String text) {
IndentGuideTestData testData = parse(text)
myFixture.configureByText("${getTestName(false)}.java", testData.documentText)
@@ -21,7 +21,9 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
import com.intellij.lang.*;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -43,22 +45,16 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.DocumentUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.IntStack;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.TIntIntHashMap;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
public class IndentsPass extends TextEditorHighlightingPass implements DumbAware {
private static final ConcurrentMap<IElementType, String> COMMENT_PREFIXES = ContainerUtil.newConcurrentMap();
private static final String NO_COMMENT_INFO_MARKER = "hopefully, noone uses this string as a comment prefix";
private static final Key<List<RangeHighlighter>> INDENT_HIGHLIGHTERS_IN_EDITOR_KEY = Key.create("INDENT_HIGHLIGHTERS_IN_EDITOR_KEY");
private static final Key<Long> LAST_TIME_INDENTS_BUILT = Key.create("LAST_TIME_INDENTS_BUILT");
@@ -302,7 +298,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
IndentsCalculator calculator = new IndentsCalculator();
calculator.calculate();
int[] lineIndents = calculator.lineIndents;
TIntIntHashMap effectiveCommentColumns = calculator.indentAfterUncomment;
List<IndentGuideDescriptor> descriptors = new ArrayList<IndentGuideDescriptor>();
@@ -312,33 +307,26 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
lines.push(0);
indents.push(0);
assert myDocument != null;
final CharSequence chars = myDocument.getCharsSequence();
for (int line = 1; line < lineIndents.length; line++) {
ProgressManager.checkCanceled();
int curIndent = lineIndents[line];
int curIndent = Math.abs(lineIndents[line]);
while (!indents.empty() && curIndent <= indents.peek()) {
ProgressManager.checkCanceled();
final int level = indents.pop();
int startLine = lines.pop();
if (level > 0) {
boolean addDescriptor = effectiveCommentColumns.contains(startLine); // Indent started at comment
if (!addDescriptor) {
for (int i = startLine; i < line; i++) {
if (level != lineIndents[i] && level != effectiveCommentColumns.get(i)) {
addDescriptor = true;
break;
}
for (int i = startLine; i < line; i++) {
if (level != Math.abs(lineIndents[i])) {
descriptors.add(createDescriptor(level, startLine, line, lineIndents));
break;
}
}
if (addDescriptor) {
descriptors.add(createDescriptor(level, startLine, line, chars));
}
}
}
int prevLine = line - 1;
int prevIndent = lineIndents[prevLine];
int prevIndent = Math.abs(lineIndents[prevLine]);
if (curIndent - prevIndent > 1) {
lines.push(prevLine);
@@ -351,79 +339,17 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
final int level = indents.pop();
int startLine = lines.pop();
if (level > 0) {
descriptors.add(createDescriptor(level, startLine, myDocument.getLineCount(), chars));
descriptors.add(createDescriptor(level, startLine, myDocument.getLineCount(), lineIndents));
}
}
return descriptors;
}
private IndentGuideDescriptor createDescriptor(int level, int startLine, int endLine, CharSequence chars) {
while (startLine > 0 && isBlankLine(startLine, chars)) startLine--;
private static IndentGuideDescriptor createDescriptor(int level, int startLine, int endLine, int[] lineIndents) {
while (startLine > 0 && lineIndents[startLine] < 0) startLine--;
return new IndentGuideDescriptor(level, startLine, endLine);
}
private boolean isBlankLine(int line, CharSequence chars) {
Document document = myDocument;
if (document == null) {
return true;
}
int startOffset = document.getLineStartOffset(line);
int endOffset = document.getLineEndOffset(line);
return CharArrayUtil.shiftForward(chars, startOffset, endOffset, " \t") >= myDocument.getLineEndOffset(line);
}
/**
* We want to treat comments specially in a way to skip comment prefix on line indent calculation.
* <p/>
* Example:
* <pre>
* if (true) {
* int i1;
* // int i2;
* int i3;
* }
* </pre>
* We want to use 'int i2;' start offset as the third line indent (though it has non-white space comment prefix (//)
* at the first column.
* <p/>
* This method tries to parse comment prefix for the language implied by the given comment type. It uses
* {@link #NO_COMMENT_INFO_MARKER} as an indicator that that information is unavailable
*
* @param commentType target comment type
* @return prefix of the comment denoted by the given type if any;
* {@link #NO_COMMENT_INFO_MARKER} otherwise
*/
@NotNull
private static String getCommentPrefix(@NotNull IElementType commentType) {
Commenter c = LanguageCommenters.INSTANCE.forLanguage(commentType.getLanguage());
if (!(c instanceof CodeDocumentationAwareCommenter)) {
COMMENT_PREFIXES.put(commentType, NO_COMMENT_INFO_MARKER);
return NO_COMMENT_INFO_MARKER;
}
CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)c;
IElementType lineCommentType = commenter.getLineCommentTokenType();
String lineCommentPrefix = commenter.getLineCommentPrefix();
if (lineCommentType != null) {
COMMENT_PREFIXES.put(lineCommentType, lineCommentPrefix == null ? NO_COMMENT_INFO_MARKER : lineCommentPrefix);
}
IElementType blockCommentType = commenter.getBlockCommentTokenType();
String blockCommentPrefix = commenter.getBlockCommentPrefix();
if (blockCommentType != null) {
COMMENT_PREFIXES.put(blockCommentType, blockCommentPrefix == null ? NO_COMMENT_INFO_MARKER : blockCommentPrefix);
}
IElementType docCommentType = commenter.getDocumentationCommentTokenType();
String docCommentPrefix = commenter.getDocumentationCommentPrefix();
if (docCommentType != null) {
COMMENT_PREFIXES.put(docCommentType, docCommentPrefix == null ? NO_COMMENT_INFO_MARKER : docCommentPrefix);
}
COMMENT_PREFIXES.putIfAbsent(commentType, NO_COMMENT_INFO_MARKER);
return COMMENT_PREFIXES.get(commentType);
}
@NotNull
private static RangeHighlighter createHighlighter(MarkupModel mm, TextRange range) {
final RangeHighlighter highlighter =
@@ -441,22 +367,8 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
@NotNull public final Map<Language, TokenSet> myComments = ContainerUtilRt.newHashMap();
/**
* We need to treat specially commented lines. Consider a situation like below:
* <pre>
* void test() {
* if (true) {
* int i;
* // int j;
* }
* }
* </pre>
* We don't want to show indent guide after 'int i;' line because un-commented line below ('int j;') would have the same indent
* level. That's why we remember 'indents after un-comment' at this collection.
*/
@NotNull public final TIntIntHashMap/* line -> indent column after un-comment */ indentAfterUncomment = new TIntIntHashMap();
@NotNull public final int[] lineIndents;
@NotNull public final int[] lineIndents; // negative value means the line is empty (or contains a comment) and indent
// (denoted by absolute value) was deduced from enclosing non-empty lines
@NotNull public final CharSequence myChars;
IndentsCalculator() {
@@ -469,26 +381,19 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
* Calculates line indents for the {@link #myDocument target document}.
*/
void calculate() {
assert myDocument != null;
final FileType fileType = myFile.getFileType();
int prevLineIndent = -1;
for (int line = 0; line < lineIndents.length; line++) {
ProgressManager.checkCanceled();
int lineStart = myDocument.getLineStartOffset(line);
int lineEnd = myDocument.getLineEndOffset(line);
final int nonWhitespaceOffset = CharArrayUtil.shiftForward(myChars, lineStart, lineEnd, " \t");
if (nonWhitespaceOffset == lineEnd) {
if (nonWhitespaceOffset == lineEnd || isComment(nonWhitespaceOffset)) { // treating commented lines in the same way as empty lines
lineIndents[line] = -1; // Blank line marker
}
else {
final int column = ((EditorImpl)myEditor).calcColumnNumber(nonWhitespaceOffset, line, true, myChars);
if (prevLineIndent > 0 && prevLineIndent > column) {
lineIndents[line] = calcIndent(line, nonWhitespaceOffset, lineEnd, column);
}
else {
lineIndents[line] = column;
}
prevLineIndent = lineIndents[line];
lineIndents[line] = ((EditorImpl)myEditor).calcColumnNumber(nonWhitespaceOffset, line, true, myChars);
}
}
@@ -520,7 +425,7 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
for (int blankLine = startLine; blankLine < line; blankLine++) {
assert lineIndents[blankLine] == -1;
lineIndents[blankLine] = Math.min(topIndent, indent);
lineIndents[blankLine] = - Math.min(topIndent, indent);
}
//noinspection AssignmentToForLoopParameter
@@ -529,18 +434,8 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
}
}
/**
* Tries to calculate given line's indent column assuming that there might be a comment at the given indent offset
* (see {@link #getCommentPrefix(IElementType)}).
*
* @param line target line
* @param indentOffset start indent offset to use for the given line
* @param lineEndOffset given line's end offset
* @param fallbackColumn column to return if it's not possible to apply comment-specific indent calculation rules
* @return given line's indent column to use
*/
private int calcIndent(int line, int indentOffset, int lineEndOffset, int fallbackColumn) {
final HighlighterIterator it = myEditor.getHighlighter().createIterator(indentOffset);
private boolean isComment(int offset) {
final HighlighterIterator it = myEditor.getHighlighter().createIterator(offset);
IElementType tokenType = it.getTokenType();
Language language = tokenType.getLanguage();
TokenSet comments = myComments.get(language);
@@ -550,27 +445,13 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
comments = definition.getCommentTokens();
}
if (comments == null) {
return fallbackColumn;
return false;
}
else {
myComments.put(language, comments);
}
}
if (comments.contains(tokenType) && indentOffset == it.getStart()) {
String prefix = COMMENT_PREFIXES.get(tokenType);
if (prefix == null) {
prefix = getCommentPrefix(tokenType);
}
if (!NO_COMMENT_INFO_MARKER.equals(prefix)) {
final int indentInsideCommentOffset = CharArrayUtil.shiftForward(myChars, indentOffset + prefix.length(), lineEndOffset, " \t");
if (indentInsideCommentOffset < lineEndOffset) {
int indent = myEditor.calcColumnNumber(indentInsideCommentOffset, line);
indentAfterUncomment.put(line, indent - prefix.length());
return indent;
}
}
}
return fallbackColumn;
return comments.contains(tokenType);
}
}
}
@@ -39,6 +39,7 @@ public class IntentionSettingsConfigurable extends BaseConfigurable implements S
}
JPanel component = myPanel.getComponent();
component.setPreferredSize(new Dimension(800, 600));
component.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
return component;
}
@@ -96,7 +96,7 @@ public abstract class IntentionSettingsTree {
myFilter = new MyFilterComponent();
myComponent = new JPanel(new BorderLayout());
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTree, SideBorder.TOP | SideBorder.RIGHT);
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTree);
myNorthPanel = new JPanel(new BorderLayout());
myNorthPanel.add(myFilter, BorderLayout.CENTER);
@@ -16,11 +16,7 @@
package com.intellij.execution.console;
import com.intellij.icons.AllIcons;
import com.intellij.lang.Language;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -41,13 +37,6 @@ public class IdeConsoleRootType extends ConsoleRootType {
return findByClass(IdeConsoleRootType.class);
}
@Nullable
@Override
public Language substituteLanguage(@NotNull Project project, @NotNull VirtualFile file) {
FileType fileType = getFileType(file);
return fileType instanceof LanguageFileType ? ((LanguageFileType)fileType).getLanguage() : null;
}
@Nullable
@Override
public Icon substituteIcon(@NotNull Project project, @NotNull VirtualFile file) {
@@ -59,10 +48,4 @@ public class IdeConsoleRootType extends ConsoleRootType {
RunIdeConsoleAction.configureConsole(file, source);
}
@Nullable
private static FileType getFileType(@NotNull VirtualFile file) {
String extension = file.getExtension();
if (extension == null) return null;
return FileTypeManager.getInstance().getFileTypeByExtension(extension);
}
}
@@ -19,10 +19,13 @@ import com.intellij.lang.Language;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.LanguageSubstitutors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -80,7 +83,7 @@ public abstract class RootType {
@Nullable
public Language substituteLanguage(@NotNull Project project, @NotNull VirtualFile file) {
return null;
return substituteLanguageImpl(getOriginalLanguage(file), file, project);
}
@Nullable
@@ -101,4 +104,23 @@ public abstract class RootType {
public void fileOpened(@NotNull VirtualFile file, @NotNull FileEditorManager source) {
}
@Nullable
protected static Language substituteLanguageImpl(Language language, VirtualFile file, Project project) {
return language != null && language != ScratchFileType.INSTANCE.getLanguage() ?
LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project) : language;
}
@Nullable
protected static FileType getOriginalFileType(@NotNull VirtualFile file) {
String extension = file.getExtension();
if (extension == null) return null;
return FileTypeManager.getInstance().getFileTypeByExtension(extension);
}
@Nullable
protected static Language getOriginalLanguage(@NotNull VirtualFile file) {
FileType fileType = getOriginalFileType(file);
return fileType instanceof LanguageFileType ? ((LanguageFileType)fileType).getLanguage() : null;
}
}
@@ -126,7 +126,6 @@ public class ScratchProjectViewPane extends ProjectViewPane {
@Nullable
private static PsiDirectory getDirectory(@NotNull Project project, @NotNull RootType rootId) {
// todo project roots not supported
String path = ScratchFileService.getInstance().getRootPath(rootId);
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
return virtualFile == null ? null : PsiManager.getInstance(project).findDirectory(virtualFile);
@@ -162,7 +161,9 @@ public class ScratchProjectViewPane extends ProjectViewPane {
List<AbstractTreeNode> list = ContainerUtil.newArrayList();
for (RootType rootId : RootType.getAllRootIds()) {
if (rootId.isHidden()) continue;
list.add(new MyRootNode(getProject(), rootId));
MyRootNode e = new MyRootNode(getProject(), rootId);
if (e.getDirectory() == null) continue;
list.add(e);
}
return list;
}
@@ -182,11 +183,15 @@ public class ScratchProjectViewPane extends ProjectViewPane {
@Override
public Collection<? extends AbstractTreeNode> getChildren() {
RootType rootType = getValue();
PsiDirectory directory = getDirectory(getProject(), rootType);
PsiDirectory directory = getDirectory();
if (directory == null) return Collections.emptyList();
return new MyPsiNode(getProject(), rootType, directory).getChildren();
}
PsiDirectory getDirectory() {
return ScratchProjectViewPane.getDirectory(getProject(), getValue());
}
@Override
protected void update(PresentationData presentation) {
presentation.setIcon(PlatformIcons.DIRECTORY_CLOSED_ICON);
@@ -17,10 +17,8 @@ package com.intellij.ide.scratch;
import com.intellij.icons.AllIcons;
import com.intellij.lang.Language;
import com.intellij.lang.PerFileMappings;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.LanguageSubstitutors;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
@@ -44,10 +42,8 @@ public final class ScratchRootType extends RootType {
@Override
public Language substituteLanguage(@NotNull Project project, @NotNull VirtualFile file) {
PerFileMappings<Language> mapping = ScratchFileService.getInstance().getScratchesMapping();
Language language = mapping.getMapping(file);
return language != null && language != ScratchFileType.INSTANCE.getLanguage() ?
LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project) : language;
Language language = ScratchFileService.getInstance().getScratchesMapping().getMapping(file);
return substituteLanguageImpl(language, file, project);
}
@Nullable
@@ -87,11 +87,14 @@ public interface Configurable extends UnnamedConfigurable {
* the configurable contains its own scrollable components.
*/
interface NoScroll {
// see ConfigurableCardPanel#create(Configurable)
}
/**
* Forbids setting an empty border to the content of the configurable.
* Required when the configurable represents is a tabbed pane.
*/
interface NoMargin {
// see ConfigurableCardPanel#create(Configurable)
}
}
@@ -36,6 +36,16 @@ public class ConfigurableCardPanel extends CardLayoutPanel<Configurable, Configu
return key;
}
/**
* Creates UI component for the specified configurable.
* If a component is created successfully the configurable will be reset.
* If the configurable implements {@link MasterDetails},
* created component will not have the following modifications.
* If the configurable does not implement {@link Configurable.NoMargin},
* this method sets an empty border with default margins for created component.
* If the configurable does not implement {@link Configurable.NoScroll},
* this method adds a scroll bars for created component.
*/
@Override
protected JComponent create(final Configurable configurable) {
return configurable == null ? null : ApplicationManager.getApplication().runReadAction(new Computable<JComponent>() {
@@ -38,6 +38,11 @@ public class FakeVirtualFile extends StubVirtualFile {
return myParent;
}
@Override
public boolean isDirectory() {
return false;
}
@NotNull
@Override
public String getPath() {
@@ -88,7 +88,7 @@ ide.windowSystem.showTooWindowButtonsSwitcher=true
ide.help.fxbrowser=false
passwordSafe.masterPassword.ttl=60
passwordSafe.masterPassword.ttl=360
passwordSafe.memorySafe.ttl=-1
ide.tree.yieldingUiUpdate=true
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -1525,8 +1525,8 @@ public class StringUtil extends StringUtilRt {
*/
@NotNull
@Contract(pure = true)
public static String formatFileSize(long size) {
return formatValue(size, null,
public static String formatFileSize(long fileSize) {
return formatValue(fileSize, null,
new String[]{"B", "K", "M", "G", "T", "P", "E"},
new long[]{1000, 1000, 1000, 1000, 1000, 1000});
}
@@ -15,6 +15,7 @@
*/
package com.intellij.util.ui;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.border.CustomLineBorder;
import javax.swing.*;
@@ -25,8 +26,7 @@ import java.awt.*;
* @author Konstantin Bulenkov
*/
public class JBUI {
private static boolean IS_HIDPI = ("true".equals(System.getProperty("hidpi")) || getSystemDPI() >= 144)
&& !("false".equals(System.getProperty("hidpi")));
private static boolean IS_HIDPI = !SystemInfo.isMac && ("true".equals(System.getProperty("hidpi")) || "true".equals(System.getProperty("is.hidpi")));
private static int getSystemDPI() {
try {