Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2015-02-11 12:38:34 +03:00
17 changed files with 291 additions and 173 deletions
+1
View File
@@ -278,6 +278,7 @@ libraryLicense(name: "json-smart", libraryName: "json-smart-1.1.1.jar", version:
libraryLicense(name: "fxg-utils", libraryName: "fxg-utils", version: "4.9.1", license: "Apache 2.0", url: "http://flex.apache.org", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "jayatana", libraryName: "jayatana", version: "1.2.4", license: "MIT License", url: "https://code.google.com/p/java-swing-ayatana/", licenseUrl: "http://opensource.org/licenses/mit-license.php")
libraryLicense(name: "ForkJoin", version: "", license: "Creative Commons Public Domain Dedication", url: "http://gee.cs.oswego.edu/dl/concurrency-interest/index.html", licenseUrl: "http://creativecommons.org/publicdomain/zero/1.0/")
libraryLicense(name: "ANTLR 4 Runtime", libraryName: "antlr-runtime-4.1.jar", version: "4.1", license: "BSD", url: "http://www.antlr.org", licenseUrl: "http://www.antlr.org/license.html")
libraryLicense(name: "minlog", libraryName: "minlog-1.2.jar", version: "1.2", license: "BSD", url: "https://github.com/EsotericSoftware/minlog", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
@@ -132,7 +132,7 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
case FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED:
if (file instanceof PsiJavaFile) {
PsiJavaFile javaFile = ((PsiJavaFile)file);
return !ImportHelper.isAlreadyImported(javaFile, item.getQualifiedName());
return item.getQualifiedName() != null && !ImportHelper.isAlreadyImported(javaFile, item.getQualifiedName());
}
default:
return false;
@@ -454,6 +454,43 @@ class Test {
}
'''
}
public void testNullQualifiedName() {
def text = '''
public class Test {
public static void main(String[] args) {
class Super {
}
/**
* {@link Su<caret>}
*/
Super aSuper = new Super();
}
}
'''
myFixture.configureByText "a.java", text
myFixture.completeBasic()
myFixture.type('\t')
myFixture.checkResult '''
public class Test {
public static void main(String[] args) {
class Super {
}
/**
* {@link Super}
*/
Super aSuper = new Super();
}
}
'''
}
public void testShortNameIfImplicitlyImported() {
javaSettings.CLASS_NAMES_IN_JAVADOC = JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED
@@ -15,53 +15,33 @@
*/
package com.intellij.psi.codeStyle;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collections;
import javax.swing.Icon;
import java.util.List;
public class EditorNotificationInfo {
private String myTitle;
private Icon myIcon;
private List<LabelWithAction> myLabelsWithActions = ContainerUtil.newArrayList();
public EditorNotificationInfo(@NotNull String title,
@NotNull LabelWithAction firstLabel,
@Nullable LabelWithAction... otherLabels)
{
myTitle = title;
myLabelsWithActions.add(firstLabel);
if (otherLabels != null) {
Collections.addAll(myLabelsWithActions, otherLabels);
}
}
public EditorNotificationInfo(@NotNull String title,
@NotNull Icon icon,
@NotNull LabelWithAction firstLabel,
@Nullable LabelWithAction... otherLabels)
{
this(title, firstLabel, otherLabels);
myIcon = icon;
}
public abstract class EditorNotificationInfo {
@NotNull
public List<LabelWithAction> getLabelAndActions() {
return myLabelsWithActions;
}
public abstract List<ActionLabelData> getLabelAndActions();
@NotNull
public abstract String getTitle();
@Nullable
public Icon getIcon() {
return myIcon;
return null;
}
@NotNull
public String getTitle() {
return myTitle;
public static class ActionLabelData {
public final String label;
public final Runnable action;
public ActionLabelData(@NotNull String label, @NotNull Runnable action) {
this.label = label;
this.action = action;
}
}
}
@@ -1,29 +0,0 @@
/*
* 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.
* 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;
import org.jetbrains.annotations.NotNull;
public class LabelWithAction {
public final String label;
public final Runnable action;
public LabelWithAction(@NotNull String label, @NotNull Runnable action) {
this.label = label;
this.action = action;
}
}
@@ -0,0 +1,122 @@
/*
* 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.
* 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.internal.statistic.editor;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.editorActions.SmartBackspaceMode;
import com.intellij.internal.statistic.CollectUsagesException;
import com.intellij.internal.statistic.UsagesCollector;
import com.intellij.internal.statistic.beans.GroupDescriptor;
import com.intellij.internal.statistic.beans.UsageDescriptor;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.richcopy.settings.RichCopySettings;
import com.intellij.openapi.util.Comparing;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
class EditorSettingsStatisticsCollector extends UsagesCollector {
@NotNull
@Override
public GroupDescriptor getGroupId() {
return GroupDescriptor.create("Editor");
}
@NotNull
@Override
public Set<UsageDescriptor> getUsages() throws CollectUsagesException {
Set<UsageDescriptor> set = new HashSet<UsageDescriptor>();
EditorSettingsExternalizable es = EditorSettingsExternalizable.getInstance();
addIfDiffers(set, es.isVirtualSpace(), false, "caretAfterLineEnd");
addIfDiffers(set, es.isCaretInsideTabs(), false, "caretInsideTabs");
addIfDiffers(set, es.isAdditionalPageAtBottom(), false, "virtualSpaceAtFileBottom");
addIfDiffers(set, es.isUseSoftWraps(SoftWrapAppliancePlaces.MAIN_EDITOR), false, "softWraps");
addIfDiffers(set, es.isUseSoftWraps(SoftWrapAppliancePlaces.CONSOLE), false, "softWraps.console");
addIfDiffers(set, es.isUseCustomSoftWrapIndent(), false, "softWraps.relativeIndent");
addIfDiffers(set, es.isAllSoftWrapsShown(), false, "softWraps.showAll");
addIfDiffers(set, es.getStripTrailingSpaces(), EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED, "stripTrailingSpaces");
addIfDiffers(set, es.isEnsureNewLineAtEOF(), false, "ensureNewlineAtEOF");
addIfDiffers(set, es.isShowQuickDocOnMouseOverElement(), false, "quickDocOnMouseHover");
addIfDiffers(set, es.isBlinkCaret(), true, "nonBlinkingCaret");
addIfDiffers(set, es.isBlockCursor(), false, "blockCaret");
addIfDiffers(set, es.isRightMarginShown(), true, "noRightMargin");
addIfDiffers(set, es.isLineNumbersShown(), false, "lineNumbers");
addIfDiffers(set, es.isFoldingOutlineShown(), true, "noFoldingOutline");
addIfDiffers(set, es.isWhitespacesShown() && es.isLeadingWhitespacesShown(), false, "showLeadingWhitespace");
addIfDiffers(set, es.isWhitespacesShown() && es.isInnerWhitespacesShown(), false, "showInnerWhitespace");
addIfDiffers(set, es.isWhitespacesShown() && es.isTrailingWhitespacesShown(), false, "showTrailingWhitespace");
addIfDiffers(set, es.isIndentGuidesShown(), true, "noIndentGuides");
addIfDiffers(set, es.isSmoothScrolling(), true, "noAnimatedScroll");
addIfDiffers(set, es.isDndEnabled(), false, "dragNDrop");
addIfDiffers(set, es.isWheelFontChangeEnabled(), false, "wheelZoom");
addIfDiffers(set, es.isMouseClickSelectionHonorsCamelWords(), true, "mouseNoCamel");
addIfDiffers(set, es.isVariableInplaceRenameEnabled(), true, "noInplaceRename");
addIfDiffers(set, es.isPreselectRename(), true, "noPreselectOnRename");
addIfDiffers(set, es.isShowInlineLocalDialog(), true, "noInlineDialog");
addIfDiffers(set, es.isRefrainFromScrolling(), false, "minimizeScrolling");
addIfDiffers(set, es.getOptions().SHOW_REFORMAT_DIALOG, true, "noReformatDialog");
addIfDiffers(set, es.getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG, true, "noOptimizeImportsDialog");
addIfDiffers(set, es.isSmartHome(), true, "noSmartHome");
addIfDiffers(set, es.isCamelWords(), false, "camelWords");
RichCopySettings rcs = RichCopySettings.getInstance();
addIfDiffers(set, rcs.isEnabled(), true, "noRichCopy");
CodeInsightSettings cis = CodeInsightSettings.getInstance();
addIfDiffers(set, cis.AUTO_POPUP_PARAMETER_INFO, true, "noParameterAutoPopup");
addIfDiffers(set, cis.AUTO_POPUP_JAVADOC_INFO, false, "javadocAutoPopup");
addIfDiffers(set, cis.AUTO_POPUP_COMPLETION_LOOKUP, true, "noCompletionAutoPopup");
addIfDiffers(set, cis.COMPLETION_CASE_SENSITIVE, CodeInsightSettings.FIRST_LETTER, "completionCaseSensitivity");
addIfDiffers(set, cis.SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS, false, "autoPopupCharComplete");
addIfDiffers(set, cis.AUTOCOMPLETE_ON_CODE_COMPLETION, true, "noAutoCompleteBasic");
addIfDiffers(set, cis.AUTOCOMPLETE_ON_SMART_TYPE_COMPLETION, true, "noAutoCompleteSmart");
addIfDiffers(set, cis.SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO, false, "parameterInfoFullSignature");
addIfDiffers(set, cis.getBackspaceMode(), SmartBackspaceMode.AUTOINDENT, "smartBackspace");
addIfDiffers(set, cis.SMART_INDENT_ON_ENTER, true, "noIndentOnEnter");
addIfDiffers(set, cis.INSERT_BRACE_ON_ENTER, true, "noBraceOnEnter");
addIfDiffers(set, cis.JAVADOC_STUB_ON_ENTER, true, "noJavadocOnEnter");
addIfDiffers(set, cis.SMART_END_ACTION, true, "noSmartEnd");
addIfDiffers(set, cis.JAVADOC_GENERATE_CLOSING_TAG, true, "noAutoCloseJavadocTags");
addIfDiffers(set, cis.SURROUND_SELECTION_ON_QUOTE_TYPED, false, "surroundByQuoteOrBrace");
addIfDiffers(set, cis.AUTOINSERT_PAIR_BRACKET, true, "noPairBracketAutoInsert");
addIfDiffers(set, cis.AUTOINSERT_PAIR_QUOTE, true, "noPairQuoteAutoInsert");
addIfDiffers(set, cis.REFORMAT_BLOCK_ON_RBRACE, true, "noReformatOnRBrace");
addIfDiffers(set, cis.REFORMAT_ON_PASTE, CodeInsightSettings.INDENT_EACH_LINE, "reformatOnPaste");
addIfDiffers(set, cis.ADD_IMPORTS_ON_PASTE, CodeInsightSettings.ASK, "importsOnPaste");
addIfDiffers(set, cis.HIGHLIGHT_BRACES, true, "noBracesHighlight");
addIfDiffers(set, cis.HIGHLIGHT_SCOPE, false, "scopeHighlight");
addIfDiffers(set, cis.HIGHLIGHT_IDENTIFIER_UNDER_CARET, true, "noIdentifierUnderCaretHighlight");
addIfDiffers(set, cis.OPTIMIZE_IMPORTS_ON_THE_FLY, false, "autoOptimizeImports");
addIfDiffers(set, cis.ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY, false, "autoAddImports");
return set;
}
private static void addIfDiffers(Set<UsageDescriptor> set, boolean value, boolean defaultValue, String featureId) {
if (value != defaultValue) {
set.add(new UsageDescriptor(featureId, 1));
}
}
private static void addIfDiffers(Set<UsageDescriptor> set, Object value, Object defaultValue, String featureIdPrefix) {
if (!Comparing.equal(value, defaultValue)) {
set.add(new UsageDescriptor(featureIdPrefix + "." + value, 1));
}
}
}
@@ -27,7 +27,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.*;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.ui.EditorNotifications;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.WeakList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,6 +35,8 @@ import org.jetbrains.annotations.TestOnly;
import java.util.List;
import static com.intellij.psi.codeStyle.EditorNotificationInfo.*;
/**
* @author Rustam Vishnyakov
*/
@@ -82,22 +84,21 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider {
@NotNull CommonCodeStyleSettings.IndentOptions userOptions,
@NotNull CommonCodeStyleSettings.IndentOptions detectedOptions)
{
NotificationLabels labels = getNotificationLabels(userOptions, detectedOptions);
final NotificationLabels labels = getNotificationLabels(userOptions, detectedOptions);
final Editor editor = fileEditor instanceof TextEditor ? ((TextEditor)fileEditor).getEditor() : null;
if (labels == null || editor == null) return null;
LabelWithAction okAction = new LabelWithAction(
ActionLabelData okAction = new ActionLabelData(
ApplicationBundle.message("code.style.indents.detector.accept"),
new Runnable() {
@Override
public void run() {
setAccepted(file);
EditorNotifications.getInstance(project).updateAllNotifications();
}
}
);
LabelWithAction disableForSingleFile = new LabelWithAction(
ActionLabelData disableForSingleFile = new ActionLabelData(
labels.revertToOldSettingsLabel,
new Runnable() {
@Override
@@ -106,24 +107,35 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider {
if (editor instanceof EditorEx) {
((EditorEx)editor).reinitSettings();
}
EditorNotifications.getInstance(project).updateAllNotifications();
}
}
);
LabelWithAction showSettings = new LabelWithAction(
ActionLabelData showSettings = new ActionLabelData(
ApplicationBundle.message("code.style.indents.detector.show.settings"),
new Runnable() {
@Override
public void run() {
ShowSettingsUtilImpl.showSettingsDialog(project, "preferences.sourceCode",
ApplicationBundle.message("settings.code.style.general.autodetect.indents"));
EditorNotifications.getInstance(project).updateAllNotifications();
}
}
);
return new EditorNotificationInfo(labels.title, okAction, disableForSingleFile, showSettings);
final List<ActionLabelData> actions = ContainerUtil.newArrayList(okAction, disableForSingleFile, showSettings);
return new EditorNotificationInfo() {
@NotNull
@Override
public List<ActionLabelData> getLabelAndActions() {
return actions;
}
@NotNull
@Override
public String getTitle() {
return labels.title;
}
};
}
@Nullable
@@ -32,6 +32,8 @@ import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.psi.codeStyle.EditorNotificationInfo.*;
/**
* @author Rustam Vishnyakov
*/
@@ -77,8 +79,15 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio
if (info.getIcon() != null) {
panel.icon(info.getIcon());
}
for (LabelWithAction action : info.getLabelAndActions()) {
panel.createActionLabel(action.label, action.action);
for (final ActionLabelData actionLabelData : info.getLabelAndActions()) {
Runnable onClickAction = new Runnable() {
@Override
public void run() {
actionLabelData.action.run();
EditorNotifications.getInstance(project).updateAllNotifications();
}
};
panel.createActionLabel(actionLabelData.label, onClickAction);
}
return panel;
}
@@ -813,6 +813,7 @@
<statistics.usagesCollector implementation="com.intellij.execution.impl.statistics.RunConfigurationTypeUsagesCollector"/>
<statistics.usagesCollector implementation="com.intellij.execution.impl.statistics.TemporaryRunConfigurationTypeUsagesCollector"/>
<statistics.usagesCollector implementation="com.intellij.openapi.fileTypes.FileTypeUsagesCollector"/>
<statistics.usagesCollector implementation="com.intellij.internal.statistic.editor.EditorSettingsStatisticsCollector"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenamePsiFileProcessor" order="last"/>
<renameInputValidator implementation="com.intellij.refactoring.rename.RenameToIgnoredDirectoryFileInputValidator" order="last"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 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.
@@ -127,8 +127,8 @@ public class DebuggerUIUtil {
JComponent component,
@Nullable final FullValueEvaluationCallbackImpl callback) {
ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(component, null);
builder.setResizable(true).setAlpha(1)
.setMovable(true)
builder.setResizable(true)/*.setAlpha(1)*/ // alpha disabled because of IDEA-136331
.setMovable(true)
.setDimensionServiceKey(project, FULL_VALUE_POPUP_DIMENSION_KEY, false)
.setRequestFocus(false);
if (callback != null) {
@@ -89,18 +89,9 @@ public interface PropertiesFile {
*/
@NotNull PsiElement addPropertyAfter(@NotNull Property property, @Nullable Property anchor) throws IncorrectOperationException;
/**
* delegates call to {@link PropertiesFile#addPropertyLast()} method
*/
@Deprecated
IProperty addProperty(String key, String value);
IProperty addPropertyFirst(String key, String value);
IProperty addPropertyLast(String key, String value);
IProperty addPropertyAfter(String key, String value, Property anchor);
/**
* @return Property key to the property value map.
* Do not modify this map. It's no use anyway.
@@ -116,4 +107,6 @@ public interface PropertiesFile {
Project getProject();
String getText();
boolean isAlphaSorted();
}
@@ -17,7 +17,6 @@ package com.intellij.codeInspection.unsorted;
import com.intellij.codeInspection.*;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.PropertiesBundle;
import com.intellij.lang.properties.PropertiesImplUtil;
import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.psi.PropertiesElementFactory;
@@ -30,11 +29,8 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
@@ -68,7 +64,7 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool {
holder.registerProblem(file, String.format(MESSAGE_TEMPLATE_WHOLE_RESOURCE_BUNDLE, resourceBundleBaseName), ProblemHighlightType.INFO, new PropertiesSorterQuickFix(true, propertiesFile));
return;
}
if (!isAlphaSorted(propertiesFile)) {
if (!propertiesFile.isAlphaSorted()) {
holder.registerProblem(file, "Properties file is unsorted", ProblemHighlightType.INFO, new PropertiesSorterQuickFix(true, propertiesFile));
}
}
@@ -81,32 +77,9 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool {
if (!(file instanceof PropertiesFileImpl)) {
return true;
}
if (!file.equals(exceptedFile)) {
if (!isAlphaSorted(file)) {
return false;
}
}
}
return true;
}
private static boolean isAlphaSorted(final @NotNull PropertiesFile propertiesFile) {
return isAlphaSorted(ContainerUtil.mapNotNull(propertiesFile.getProperties(), new NullableFunction<IProperty, String>() {
@Nullable
@Override
public String fun(IProperty property) {
return property.getKey();
}
}));
}
private static boolean isAlphaSorted(final List<String> keys) {
String prevKey = null;
for (String key : keys) {
if (prevKey != null && prevKey.compareTo(key) > 0) {
if (!file.equals(exceptedFile) && !file.isAlphaSorted()) {
return false;
}
prevKey = key;
}
return true;
}
@@ -137,7 +110,7 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool {
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final boolean force = myFilesToSort.length == 1;
for (PropertiesFile file : myFilesToSort) {
if (!force && isAlphaSorted(file)) {
if (!force && file.isAlphaSorted()) {
continue;
}
sortPropertiesFile(file);
@@ -33,10 +33,7 @@ import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* @author Konstantin Bulenkov
@@ -162,4 +159,19 @@ public class PropertiesImplUtil extends PropertiesUtil {
}
return getResourceBundle(baseName, baseDirectory);
}
public static boolean isAlphaSorted(final Collection<? extends IProperty> properties) {
String previousKey = null;
for (IProperty property : properties) {
final String key = property.getKey();
if (key == null) {
return false;
}
if (previousKey != null && previousKey.compareTo(key) > 0) {
return false;
}
previousKey = key;
}
return true;
}
}
@@ -25,6 +25,7 @@ import com.intellij.lang.properties.parsing.PropertiesElementTypes;
import com.intellij.lang.properties.psi.PropertiesElementFactory;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
@@ -44,9 +45,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
private static final Logger LOG = Logger.getInstance(PropertiesFileImpl.class);
private static final TokenSet PROPERTIES_LIST_SET = TokenSet.create(PropertiesElementTypes.PROPERTIES_LIST);
private volatile MostlySingularMultiMap<String,IProperty> myPropertiesMap; //guarded by lock
private volatile List<IProperty> myProperties; //guarded by lock
private volatile boolean myAlphaSorted;
private final Object lock = new Object();
public PropertiesFileImpl(FileViewProvider viewProvider) {
@@ -87,10 +90,12 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
propertiesMap.add(key, property);
properties.add(property);
}
final boolean isAlphaSorted = PropertiesImplUtil.isAlphaSorted(properties);
synchronized (lock) {
if (myPropertiesMap != null) return;
myProperties = properties;
myPropertiesMap = propertiesMap;
myAlphaSorted = isAlphaSorted;
}
}
@@ -135,12 +140,30 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
@Override
@NotNull
public PsiElement addProperty(@NotNull IProperty property) throws IncorrectOperationException {
if (haveToAddNewLine()) {
insertLineBreakBefore(null);
final IProperty position = findInsertionPosition(property);
return addPropertyAfter((Property)property, (Property)position);
}
private IProperty findInsertionPosition(@NotNull IProperty property) {
synchronized (lock) {
ensurePropertiesLoaded();
if (myProperties.isEmpty()) {
return null;
}
if (myAlphaSorted) {
final int insertIndex = Collections.binarySearch(myProperties, property, new Comparator<IProperty>() {
@Override
public int compare(IProperty p1, IProperty p2) {
final String k1 = p1.getKey();
final String k2 = p2.getKey();
LOG.assertTrue(k1 != null && k2 != null);
return k1.compareTo(k2);
}
});
return insertIndex == -1 ? null :myProperties.get(insertIndex < 0 ? - insertIndex - 2 : insertIndex);
}
return myProperties.get(myProperties.size() - 1);
}
final TreeElement copy = ChangeUtil.copyToElement(property.getPsiElement());
getPropertiesList().addChild(copy);
return copy.getPsi();
}
@Override
@@ -171,18 +194,6 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
return (IProperty)addProperty(PropertiesElementFactory.createProperty(getProject(), key, value));
}
@NotNull
@Override
public IProperty addPropertyFirst(String key, String value) {
return (IProperty)addPropertyAfter((Property) PropertiesElementFactory.createProperty(getProject(), key, value), null);
}
@NotNull
@Override
public IProperty addPropertyLast(String key, String value) {
return addProperty(key, value);
}
@NotNull
@Override
public IProperty addPropertyAfter(String key, String value, @Nullable Property anchor) {
@@ -208,6 +219,14 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
return result;
}
@Override
public boolean isAlphaSorted() {
synchronized (lock) {
ensurePropertiesLoaded();
return myAlphaSorted;
}
}
@Override
public void clearCaches() {
super.clearCaches();
@@ -120,16 +120,6 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile {
return null;
}
@Override
public IProperty addPropertyFirst(String key, String value) {
return null;
}
@Override
public IProperty addPropertyLast(String key, String value) {
return null;
}
@Override
public IProperty addPropertyAfter(String key, String value, Property anchor) {
return null;
@@ -202,6 +192,11 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile {
return getContainingFile().getText();
}
@Override
public boolean isAlphaSorted() {
return PropertiesImplUtil.isAlphaSorted(getProperties());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -65,17 +65,9 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle
}
final PropertiesFile propertiesFile = myResourceBundle.getDefaultPropertiesFile();
if (myAlphaSorted) {
final Pair<IProperty, Integer> propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile);
if (propertyAndPosition == null) {
propertiesFile.addPropertyFirst(key, value);
myKeysOrder.add(0, key);
} else {
propertiesFile.addPropertyAfter(key, value, (Property)propertyAndPosition.getFirst());
final Integer position = propertyAndPosition.getSecond();
myKeysOrder.add(position, key);
}
propertiesFile.addProperty(key, value);
} else {
propertiesFile.addPropertyLast(key, value);
insertPropertyLast(key, value, propertiesFile);
if (myOrdered) {
myKeysOrder.add(key);
}
@@ -85,14 +77,14 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle
@Override
public void insertTranslation(String key, String value, final PropertiesFile propertiesFile) {
if (myOrdered) {
final Pair<IProperty, Integer> propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile);
if (propertyAndPosition == null) {
propertiesFile.addPropertyFirst(key, value);
} else {
propertiesFile.addPropertyAfter(key, value, (Property)propertyAndPosition.getFirst());
if (myAlphaSorted) {
propertiesFile.addProperty(key, value);
return;
}
final Pair<IProperty, Integer> propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile);
propertiesFile.addPropertyAfter(key, value, propertyAndPosition == null ? null :(Property)propertyAndPosition.getFirst());
} else {
propertiesFile.addPropertyLast(key, value);
insertPropertyLast(key, value, propertiesFile);
}
}
@@ -100,13 +92,7 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle
if (myKeysOrder.isEmpty()) {
return null;
}
final int prevPosition;
if (myAlphaSorted) {
final int rawInsertionPosition = Collections.binarySearch(myKeysOrder, key);
prevPosition = rawInsertionPosition < 0 ? - rawInsertionPosition - 2 : rawInsertionPosition - 1;
} else {
prevPosition = myKeysOrder.indexOf(key);
}
final int prevPosition = myKeysOrder.indexOf(key);
for (int i = prevPosition; i >= 0 ; i--) {
final String prevKey = myKeysOrder.get(i);
final IProperty property = file.findPropertyByKey(prevKey);
@@ -117,6 +103,12 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle
return null;
}
public void insertPropertyLast(String key, String value, PropertiesFile propertiesFile) {
final List<IProperty> properties = propertiesFile.getProperties();
final IProperty lastProperty = properties.isEmpty() ? null : properties.get(properties.size() - 1);
propertiesFile.addPropertyAfter(key, value, (Property)lastProperty);
}
@Override
public void reload() {
final List<String> keysOrder = keysOrder(myResourceBundle);
@@ -124,7 +116,7 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle
if (myOrdered) {
Collections.reverse(keysOrder);
myAlphaSorted = isAlphaSorted(keysOrder);
myKeysOrder = keysOrder;
myKeysOrder = myAlphaSorted ? null : keysOrder;
} else {
myKeysOrder = null;
}
@@ -601,6 +601,7 @@ unboxing
unbuffered
uncomment
uncommented
uncommenting
undef
underwave
undoable