Merge remote-tracking branch 'origin/master'

This commit is contained in:
Evgeny Zakrevsky
2012-10-17 23:49:35 +04:00
57 changed files with 1853 additions and 30 deletions
@@ -109,9 +109,10 @@ public abstract class LanguageCodeStyleSettingsProvider {
}
/**
* @return Array of predefined code styles (empty array by default).
* @deprecated use PredefinedCodeStyle extension point instead
*/
@NotNull
@Deprecated
public PredefinedCodeStyle[] getPredefinedCodeStyles() {
return PredefinedCodeStyle.EMPTY_ARRAY;
}
@@ -17,12 +17,15 @@ package com.intellij.psi.codeStyle;
import com.intellij.lang.Language;
import com.intellij.openapi.extensions.ExtensionPointName;
import org.jetbrains.annotations.NotNull;
/**
* @author Rustam Vishnyakov
*/
public abstract class PredefinedCodeStyle {
public static final ExtensionPointName<PredefinedCodeStyle> EP_NAME =
ExtensionPointName.create("com.intellij.predefinedCodeStyle");
public final static PredefinedCodeStyle[] EMPTY_ARRAY = new PredefinedCodeStyle[]{};
private final String myName;
@@ -46,9 +49,17 @@ public abstract class PredefinedCodeStyle {
public boolean equals(Object obj) {
if (!(obj instanceof PredefinedCodeStyle)) return false;
PredefinedCodeStyle otherStyle = (PredefinedCodeStyle)obj;
return myName.equals(otherStyle.getName());
return myName.equals(otherStyle.getName()) &&
myLanguage.equals(otherStyle.getLanguage());
}
@Override
public int hashCode() {
int result = myName.hashCode();
result = 31 * result + myLanguage.hashCode();
return result;
}
public String getName() {
return myName;
}
@@ -57,7 +68,8 @@ public abstract class PredefinedCodeStyle {
public String toString() {
return myName;
}
@NotNull
public Language getLanguage() {
return myLanguage;
}
@@ -62,14 +62,16 @@ public abstract class CodeStyleAbstractConfigurable implements Configurable, Opt
@Override
public void reset() {
if (myPanel != null) {
myPanel.reset(mySettings);
}
reset(mySettings);
}
public void resetFromClone(){
reset(myCloneSettings);
}
public void reset(CodeStyleSettings settings) {
if (myPanel != null) {
myPanel.reset(myCloneSettings);
myPanel.reset(settings);
}
}
@@ -40,9 +40,7 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.*;
import java.util.List;
/**
@@ -357,9 +355,20 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
}
private PredefinedCodeStyle[] getPredefinedStyles() {
LanguageCodeStyleSettingsProvider provider = LanguageCodeStyleSettingsProvider.forLanguage(getDefaultLanguage());
if (provider == null) return new PredefinedCodeStyle[0];
return provider.getPredefinedCodeStyles();
final Language language = getDefaultLanguage();
final List<PredefinedCodeStyle> result = new ArrayList<PredefinedCodeStyle>();
for (PredefinedCodeStyle codeStyle : PredefinedCodeStyle.EP_NAME.getExtensions()) {
if (codeStyle.getLanguage().equals(language)) {
result.add(codeStyle);
}
}
final LanguageCodeStyleSettingsProvider provider = LanguageCodeStyleSettingsProvider.forLanguage(getDefaultLanguage());
if (provider != null) {
result.addAll(Arrays.asList(provider.getPredefinedCodeStyles()));
}
return result.toArray(new PredefinedCodeStyle[result.size()]);
}
@@ -532,7 +541,16 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
@Override
protected void resetImpl(CodeStyleSettings settings) {
myConfigurable.reset();
if (myConfigurable instanceof CodeStyleAbstractConfigurable) {
// when a predefined style is chosen and the configurable is wrapped in a tab,
// we apply it to CLONED code style settings and then pass them to this method to reset,
// usual reset() won't work in such case
((CodeStyleAbstractConfigurable)myConfigurable).reset(settings);
}
else {
// todo: support for other configurables
myConfigurable.reset();
}
}
}
@@ -48,7 +48,6 @@ import com.intellij.openapi.editor.impl.EditorFactoryImpl;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
@@ -268,7 +267,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
EmptyAction.registerActionShortcuts(myHistoryViewer.getComponent(), myConsoleEditor.getComponent());
}
private boolean isConsoleEditorEnabled() {
public boolean isConsoleEditorEnabled() {
return myPanel.getComponentCount() > 1;
}
@@ -645,19 +644,11 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
}
public void setLanguage(Language language) {
int offset = getCurrentEditor().getCaretModel().getOffset();
myVirtualFile.setLanguage(language);
// setViewProvider() call is required otherwise psiFile will stay the same!
FileManager fileManager = ((PsiManagerEx)PsiManager.getInstance(myProject)).getFileManager();
fileManager.setViewProvider(myVirtualFile, fileManager.createFileViewProvider(myVirtualFile, true));
reparsePsiFile();
if (!isConsoleEditorEnabled()) {
FileEditorManagerEx editorManagerEx = FileEditorManagerEx.getInstanceEx(myProject);
for (EditorWindow window : editorManagerEx.getWindows()) {
editorManagerEx.closeFile(myVirtualFile, window);
}
editorManagerEx.openTextEditor(new OpenFileDescriptor(myProject, myVirtualFile, offset), true);
}
}
public void setInputText(final String query) {
@@ -515,6 +515,8 @@
<extensionPoint name="langCodeStyleSettingsProvider" interface="com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider"/>
<extensionPoint name="predefinedCodeStyle" interface="com.intellij.psi.codeStyle.PredefinedCodeStyle"/>
<extensionPoint name="semContributor"
beanClass="com.intellij.semantic.SemContributorEP" area="IDEA_PROJECT"/>
+4
View File
@@ -332,6 +332,10 @@
<inlineActionHandler implementation="org.jetbrains.android.refactoring.AndroidInlineStyleHandler"/>
<inlineActionHandler implementation="org.jetbrains.android.refactoring.AndroidInlineLayoutHandler" order="first"/>
<lang.formatter language="XML" implementationClass="org.jetbrains.android.formatter.AndroidXmlFormattingModelBuilder"/>
<codeStyleSettingsProvider implementation="org.jetbrains.android.formatter.AndroidXmlCodeStyleSettingsProvider"/>
<predefinedCodeStyle implementation="org.jetbrains.android.formatter.AndroidXmlPredefinedCodeStyle"/>
</extensions>
<extensionPoints>
@@ -0,0 +1,329 @@
package org.jetbrains.android.formatter;
import com.intellij.application.options.CodeStyleAbstractPanel;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlCodeStylePanel extends CodeStyleAbstractPanel {
private final JPanel myPanel;
private final JBCheckBox myUseCustomSettings;
private final List<MyFileSpecificPanel> myCodeStylePanels;
private final JPanel myFileSpecificCodeStylesPanel;
AndroidXmlCodeStylePanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) {
super(XMLLanguage.INSTANCE, currentSettings, settings);
myPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
myPanel.setBorder(IdeBorderFactory.createEmptyBorder(2, 2, 2, 2));
myUseCustomSettings = new JBCheckBox("Use custom formatting settings for Android XML files");
myPanel.add(myUseCustomSettings);
myCodeStylePanels = new ArrayList<MyFileSpecificPanel>();
myFileSpecificCodeStylesPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
myPanel.add(myFileSpecificCodeStylesPanel);
myUseCustomSettings.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
UIUtil.setEnabled(myFileSpecificCodeStylesPanel, myUseCustomSettings.isSelected(), true);
}
});
myCodeStylePanels.add(new ManifestCodeStylePanel());
myCodeStylePanels.add(new LayoutCodeStylePanel());
myCodeStylePanels.add(new ValueResourcesCodeStylePanel());
myCodeStylePanels.add(new OtherCodeStylePanel());
for (MyFileSpecificPanel panel : myCodeStylePanels) {
final JPanel titledPanel = new JPanel(new BorderLayout());
titledPanel.setBorder(IdeBorderFactory.createTitledBorder(panel.getTitle()));
titledPanel.add(panel, BorderLayout.CENTER);
myFileSpecificCodeStylesPanel.add(titledPanel);
}
}
@Override
protected int getRightMargin() {
return 0;
}
@Nullable
@Override
protected EditorHighlighter createHighlighter(EditorColorsScheme scheme) {
return null;
}
@NotNull
@Override
protected FileType getFileType() {
return XmlFileType.INSTANCE;
}
@Nullable
@Override
protected String getPreviewText() {
return null;
}
@Override
public void apply(CodeStyleSettings settings) {
final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings);
androidSettings.USE_CUSTOM_SETTINGS = myUseCustomSettings.isSelected();
for (MyFileSpecificPanel panel : myCodeStylePanels) {
panel.apply(androidSettings);
}
}
@Override
public boolean isModified(CodeStyleSettings settings) {
final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings);
if (androidSettings.USE_CUSTOM_SETTINGS != myUseCustomSettings.isSelected()) {
return true;
}
for (MyFileSpecificPanel panel : myCodeStylePanels) {
if (panel.isModified(androidSettings)) {
return true;
}
}
return false;
}
@Nullable
@Override
public JComponent getPanel() {
return myPanel;
}
@Override
protected void resetImpl(CodeStyleSettings settings) {
final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings);
myUseCustomSettings.setSelected(androidSettings.USE_CUSTOM_SETTINGS);
UIUtil.setEnabled(myFileSpecificCodeStylesPanel, androidSettings.USE_CUSTOM_SETTINGS, true);
for (MyFileSpecificPanel panel : myCodeStylePanels) {
panel.resetImpl(androidSettings);
}
}
public abstract static class MyFileSpecificPanel<T extends AndroidXmlCodeStyleSettings.MySettings> extends JPanel {
private JPanel myPanel;
private JPanel myAdditionalOptionsPanel;
private JComboBox myWrapAttributesCombo;
protected JBCheckBox myInsertLineBreakBeforeFirstAttributeCheckBox;
private final String myTitle;
private final ContextSpecificSettingsProviders.Provider<T> mySettingsProvider;
protected MyFileSpecificPanel(String title, ContextSpecificSettingsProviders.Provider<T> provider) {
myTitle = title;
mySettingsProvider = provider;
}
protected void init() {
final JPanel panel = getAdditionalOptionsPanel();
if (panel != null) {
myAdditionalOptionsPanel.add(panel, BorderLayout.CENTER);
}
else {
myAdditionalOptionsPanel.setVisible(false);
}
setLayout(new BorderLayout());
add(myPanel, BorderLayout.CENTER);
fillWrappingCombo(myWrapAttributesCombo);
}
@Nullable
public JPanel getAdditionalOptionsPanel() {
return null;
}
public final void apply(AndroidXmlCodeStyleSettings settings) {
apply(mySettingsProvider.getSettings(settings));
}
protected void apply(T s) {
s.WRAP_ATTRIBUTES = ourWrappings[myWrapAttributesCombo.getSelectedIndex()];
s.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = myInsertLineBreakBeforeFirstAttributeCheckBox.isSelected();
}
public final boolean isModified(AndroidXmlCodeStyleSettings settings) {
return isModified(mySettingsProvider.getSettings(settings));
}
protected boolean isModified(T s) {
if (s.WRAP_ATTRIBUTES != ourWrappings[myWrapAttributesCombo.getSelectedIndex()]) {
return true;
}
if (s.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE != myInsertLineBreakBeforeFirstAttributeCheckBox.isSelected()) {
return true;
}
return false;
}
protected final void resetImpl(AndroidXmlCodeStyleSettings settings) {
resetImpl(mySettingsProvider.getSettings(settings));
}
protected void resetImpl(T s) {
myWrapAttributesCombo.setSelectedIndex(getIndexForWrapping(s.WRAP_ATTRIBUTES));
myInsertLineBreakBeforeFirstAttributeCheckBox.setSelected(s.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE);
}
@NotNull
public String getTitle() {
return myTitle;
}
}
private static class LayoutCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.LayoutSettings> {
private JPanel myPanel;
private JBCheckBox myInsertNewLineBeforeTagCheckBox;
public LayoutCodeStylePanel() {
super("Layout Files", ContextSpecificSettingsProviders.LAYOUT);
init();
}
@Nullable
@Override
public JPanel getAdditionalOptionsPanel() {
return myPanel;
}
@Override
protected boolean isModified(AndroidXmlCodeStyleSettings.LayoutSettings s) {
if (super.isModified(s)) {
return true;
}
return myInsertNewLineBeforeTagCheckBox.isSelected() != s.INSERT_BLANK_LINE_BEFORE_TAG;
}
@Override
protected void resetImpl(AndroidXmlCodeStyleSettings.LayoutSettings s) {
super.resetImpl(s);
myInsertNewLineBeforeTagCheckBox.setSelected(s.INSERT_BLANK_LINE_BEFORE_TAG);
}
@Override
protected void apply(AndroidXmlCodeStyleSettings.LayoutSettings s) {
super.apply(s);
s.INSERT_BLANK_LINE_BEFORE_TAG = myInsertNewLineBeforeTagCheckBox.isSelected();
}
}
public static class ManifestCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.ManifestSettings> {
private final JBCheckBox myGroupTagsCheckBox;
private JPanel myPanel;
public ManifestCodeStylePanel() {
super("AndroidManifest.xml", ContextSpecificSettingsProviders.MANIFEST);
myPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
myGroupTagsCheckBox = new JBCheckBox("Group tags with the same name");
myPanel.add(myGroupTagsCheckBox);
init();
}
@Nullable
@Override
public JPanel getAdditionalOptionsPanel() {
return myPanel;
}
@Override
protected void apply(AndroidXmlCodeStyleSettings.ManifestSettings s) {
super.apply(s);
s.GROUP_TAGS_WITH_SAME_NAME = myGroupTagsCheckBox.isSelected();
}
@Override
protected boolean isModified(AndroidXmlCodeStyleSettings.ManifestSettings s) {
if (super.isModified(s)) {
return true;
}
return s.GROUP_TAGS_WITH_SAME_NAME != myGroupTagsCheckBox.isSelected();
}
@Override
protected void resetImpl(AndroidXmlCodeStyleSettings.ManifestSettings s) {
super.resetImpl(s);
myGroupTagsCheckBox.setSelected(s.GROUP_TAGS_WITH_SAME_NAME);
}
}
public static class ValueResourcesCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.ValueResourceFileSettings> {
private final JBCheckBox myInsertLineBreaksAroundStyleCheckBox;
private JPanel myPanel;
public ValueResourcesCodeStylePanel() {
super("Value Resource Files and Selectors", ContextSpecificSettingsProviders.VALUE_RESOURCE_FILE);
myPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
myInsertLineBreaksAroundStyleCheckBox = new JBCheckBox("Insert line breaks around style declaration");
myPanel.add(myInsertLineBreaksAroundStyleCheckBox);
init();
myInsertLineBreakBeforeFirstAttributeCheckBox.setVisible(false);
}
@Nullable
@Override
public JPanel getAdditionalOptionsPanel() {
return myPanel;
}
@Override
protected void apply(AndroidXmlCodeStyleSettings.ValueResourceFileSettings s) {
super.apply(s);
s.INSERT_LINE_BREAKS_AROUND_STYLE = myInsertLineBreaksAroundStyleCheckBox.isSelected();
}
@Override
protected boolean isModified(AndroidXmlCodeStyleSettings.ValueResourceFileSettings s) {
if (super.isModified(s)) {
return true;
}
return s.INSERT_LINE_BREAKS_AROUND_STYLE != myInsertLineBreaksAroundStyleCheckBox.isSelected();
}
@Override
protected void resetImpl(AndroidXmlCodeStyleSettings.ValueResourceFileSettings s) {
super.resetImpl(s);
myInsertLineBreaksAroundStyleCheckBox.setSelected(s.INSERT_LINE_BREAKS_AROUND_STYLE);
}
}
public static class OtherCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.OtherSettings> {
public OtherCodeStylePanel() {
super("Other XML resource files", ContextSpecificSettingsProviders.OTHER);
init();
myInsertLineBreakBeforeFirstAttributeCheckBox.setVisible(false);
}
}
}
@@ -0,0 +1,194 @@
package org.jetbrains.android.formatter;
import com.intellij.formatting.FormattingDocumentModel;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import com.intellij.psi.formatter.xml.XmlPolicy;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.DomManager;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.android.dom.resources.Style;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlCodeStyleSettings extends CustomCodeStyleSettings {
public boolean USE_CUSTOM_SETTINGS = false;
public LayoutSettings LAYOUT_SETTINGS = new LayoutSettings();
public ManifestSettings MANIFEST_SETTINGS = new ManifestSettings();
public ValueResourceFileSettings VALUE_RESOURCE_FILE_SETTINGS = new ValueResourceFileSettings();
public OtherSettings OTHER_SETTINGS = new OtherSettings();
public AndroidXmlCodeStyleSettings(CodeStyleSettings container) {
super("AndroidXmlCodeStyleSettings", container);
}
public static AndroidXmlCodeStyleSettings getInstance(CodeStyleSettings settings) {
return settings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
}
@Override
public Object clone() {
try {
final AndroidXmlCodeStyleSettings cloned = (AndroidXmlCodeStyleSettings)super.clone();
cloned.LAYOUT_SETTINGS = (LayoutSettings)LAYOUT_SETTINGS.clone();
cloned.MANIFEST_SETTINGS = (ManifestSettings)MANIFEST_SETTINGS.clone();
cloned.VALUE_RESOURCE_FILE_SETTINGS = (ValueResourceFileSettings)VALUE_RESOURCE_FILE_SETTINGS.clone();
cloned.OTHER_SETTINGS = (OtherSettings)OTHER_SETTINGS.clone();
return cloned;
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public static class MySettings implements JDOMExternalizable, Cloneable {
public int WRAP_ATTRIBUTES;
public boolean INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE;
@Override
public void readExternal(Element element) throws InvalidDataException {
XmlSerializer.deserializeInto(this, element);
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
XmlSerializer.serializeInto(this, element, new SkipDefaultValuesSerializationFilters());
}
public XmlPolicy createXmlPolicy(CodeStyleSettings settings, FormattingDocumentModel documentModel) {
return new AndroidXmlPolicy(settings, this, documentModel);
}
@Override
protected MySettings clone() throws CloneNotSupportedException {
try {
return (MySettings)super.clone();
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
public static class LayoutSettings extends MySettings {
public boolean INSERT_BLANK_LINE_BEFORE_TAG = true;
{
WRAP_ATTRIBUTES = CommonCodeStyleSettings.WRAP_ALWAYS;
INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = true;
}
@Override
public XmlPolicy createXmlPolicy(CodeStyleSettings settings, FormattingDocumentModel documentModel) {
return new AndroidXmlPolicy(settings, this, documentModel) {
@Override
public boolean insertLineBreakBeforeTag(XmlTag xmlTag) {
return INSERT_BLANK_LINE_BEFORE_TAG;
}
@Override
public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
return INSERT_BLANK_LINE_BEFORE_TAG;
}
};
}
}
public static class ManifestSettings extends MySettings {
public boolean GROUP_TAGS_WITH_SAME_NAME = true;
{
WRAP_ATTRIBUTES = CommonCodeStyleSettings.WRAP_ALWAYS;
INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = true;
}
@Override
public XmlPolicy createXmlPolicy(CodeStyleSettings settings, FormattingDocumentModel documentModel) {
return new AndroidXmlPolicy(settings, this, documentModel) {
@Override
public boolean insertLineBreakBeforeTag(XmlTag xmlTag) {
if (GROUP_TAGS_WITH_SAME_NAME) {
PsiElement element = getPrevSiblingElement(xmlTag);
if (element instanceof XmlTag) {
final String name1 = ((XmlTag)element).getName();
final String name2 = xmlTag.getName();
if (!name1.equals(name2)) {
element = getPrevSiblingElement(element);
if (element instanceof XmlTag && ((XmlTag)element).getName().equals(name1)) {
return true;
}
element = getNextSiblingElement(xmlTag);
return element instanceof XmlTag && ((XmlTag)element).getName().equals(name2);
}
}
}
return false;
}
@Override
public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
return GROUP_TAGS_WITH_SAME_NAME && tag.getParentTag() == null;
}
};
}
}
public static class ValueResourceFileSettings extends MySettings {
public boolean INSERT_LINE_BREAKS_AROUND_STYLE = true;
{
WRAP_ATTRIBUTES = CommonCodeStyleSettings.DO_NOT_WRAP;
INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = false;
}
@Override
public XmlPolicy createXmlPolicy(CodeStyleSettings settings, FormattingDocumentModel documentModel) {
return new AndroidXmlPolicy(settings, this, documentModel) {
@Override
public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
if (!INSERT_LINE_BREAKS_AROUND_STYLE) {
return false;
}
final XmlTag[] subTags = tag.getSubTags();
return subTags.length != 0 && isStyleTag(subTags[0]);
}
@Override
public boolean insertLineBreakBeforeTag(XmlTag xmlTag) {
if (!INSERT_LINE_BREAKS_AROUND_STYLE) {
return false;
}
if (isStyleTag(xmlTag)) {
return true;
}
final PsiElement sibling = getPrevSiblingElement(xmlTag);
return sibling instanceof XmlTag && isStyleTag((XmlTag)sibling);
}
private boolean isStyleTag(XmlTag tag) {
return DomManager.getDomManager(tag.getProject()).
getDomElement(tag) instanceof Style;
}
};
}
}
public static class OtherSettings extends MySettings {
{
WRAP_ATTRIBUTES = CommonCodeStyleSettings.WRAP_ALWAYS;
INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = true;
}
}
}
@@ -0,0 +1,52 @@
package org.jetbrains.android.formatter;
import com.intellij.application.options.CodeStyleAbstractConfigurable;
import com.intellij.application.options.CodeStyleAbstractPanel;
import com.intellij.lang.Language;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.options.Configurable;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
@NotNull
@Override
public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) {
return new CodeStyleAbstractConfigurable(settings, originalSettings, getConfigurableDisplayName()){
protected CodeStyleAbstractPanel createPanel(final CodeStyleSettings settings) {
return new AndroidXmlCodeStylePanel(getCurrentSettings(), settings);
}
public String getHelpTopic() {
return null;
}
};
}
@Override
public String getConfigurableDisplayName() {
return "Android";
}
@Override
public boolean hasSettingsPage() {
return false;
}
@Nullable
@Override
public Language getLanguage() {
return XMLLanguage.INSTANCE;
}
@Override
public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
return new AndroidXmlCodeStyleSettings(settings);
}
}
@@ -0,0 +1,63 @@
package org.jetbrains.android.formatter;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.formatter.xml.XmlBlock;
import com.intellij.psi.formatter.xml.XmlPolicy;
import com.intellij.psi.formatter.xml.XmlTagBlock;
import org.jetbrains.annotations.NotNull;
/**
* @author Eugene.Kudelevsky
*/
class AndroidXmlFormattingModel implements FormattingModel {
private final FormattingModel myModel;
private final Block myRootBlock;
public AndroidXmlFormattingModel(FormattingModel model,
CodeStyleSettings settings,
final AndroidXmlCodeStyleSettings.MySettings customSettings) {
myModel = model;
final Block block = myModel.getRootBlock();
if (block instanceof XmlBlock) {
final XmlBlock b = (XmlBlock)block;
final XmlPolicy policy = customSettings.createXmlPolicy(settings, getDocumentModel());
myRootBlock = new XmlBlock(b.getNode(), b.getWrap(), b.getAlignment(), policy, b.getIndent(), b.getTextRange()) {
@Override
protected XmlTagBlock createTagBlock(ASTNode child, Indent indent, Wrap wrap, Alignment alignment) {
return new XmlTagBlock(child, wrap, alignment, myXmlFormattingPolicy,
indent != null ? indent : Indent.getNoneIndent(),
isPreserveSpace());
}
};
}
else {
myRootBlock = block;
}
}
@NotNull
public Block getRootBlock() {
return myRootBlock;
}
@NotNull
public FormattingDocumentModel getDocumentModel() {
return myModel.getDocumentModel();
}
public TextRange replaceWhiteSpace(TextRange textRange, String whiteSpace) {
return myModel.replaceWhiteSpace(textRange, whiteSpace);
}
public TextRange shiftIndentInsideRange(TextRange range, int indent) {
return myModel.shiftIndentInsideRange(range, indent);
}
public void commitChanges() {
myModel.commitChanges();
}
}
@@ -0,0 +1,81 @@
package org.jetbrains.android.formatter;
import com.intellij.formatting.CustomFormattingModelBuilder;
import com.intellij.formatting.FormattingModel;
import com.intellij.lang.ASTNode;
import com.intellij.lang.xml.XmlFormattingModelBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.xml.DomFileDescription;
import com.intellij.util.xml.DomManager;
import org.jetbrains.android.dom.AndroidResourceDomFileDescription;
import org.jetbrains.android.dom.color.ColorDomFileDescription;
import org.jetbrains.android.dom.drawable.DrawableStateListDomFileDescription;
import org.jetbrains.android.dom.layout.LayoutDomFileDescription;
import org.jetbrains.android.dom.manifest.ManifestDomFileDescription;
import org.jetbrains.android.dom.resources.ResourcesDomFileDescription;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlFormattingModelBuilder implements CustomFormattingModelBuilder {
private final XmlFormattingModelBuilder myXmlFormattingModelBuilder = new XmlFormattingModelBuilder();
@Override
public boolean isEngagedToFormat(PsiElement context) {
return getContextSpecificSettings(context) != null;
}
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
final FormattingModel baseModel = myXmlFormattingModelBuilder.createModel(element, settings);
final AndroidXmlCodeStyleSettings baseSettings = AndroidXmlCodeStyleSettings.getInstance(settings);
if (!baseSettings.USE_CUSTOM_SETTINGS) {
return baseModel;
}
final ContextSpecificSettingsProviders.Provider provider = getContextSpecificSettings(element);
final AndroidXmlCodeStyleSettings.MySettings s = provider != null ? provider.getSettings(baseSettings) : null;
return s != null ? new AndroidXmlFormattingModel(baseModel, settings, s) : baseModel;
}
@Nullable
@Override
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
return myXmlFormattingModelBuilder.getRangeAffectingIndent(file, offset, elementAtOffset);
}
@Nullable
private static ContextSpecificSettingsProviders.Provider getContextSpecificSettings(PsiElement context) {
final PsiFile file = context.getContainingFile();
if (!(file instanceof XmlFile) ||
AndroidFacet.getInstance(file) == null) {
return null;
}
final DomFileDescription<?> description = DomManager.getDomManager(
context.getProject()).getDomFileDescription((XmlFile)file);
if (description instanceof LayoutDomFileDescription) {
return ContextSpecificSettingsProviders.LAYOUT;
}
else if (description instanceof ManifestDomFileDescription) {
return ContextSpecificSettingsProviders.MANIFEST;
}
else if (description instanceof ResourcesDomFileDescription ||
description instanceof DrawableStateListDomFileDescription ||
description instanceof ColorDomFileDescription) {
return ContextSpecificSettingsProviders.VALUE_RESOURCE_FILE;
}
else if (description instanceof AndroidResourceDomFileDescription) {
return ContextSpecificSettingsProviders.OTHER;
}
return null;
}
}
@@ -0,0 +1,74 @@
package org.jetbrains.android.formatter;
import com.intellij.formatting.FormattingDocumentModel;
import com.intellij.formatting.WrapType;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.formatter.xml.XmlPolicy;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlPolicy extends XmlPolicy {
private final AndroidXmlCodeStyleSettings.MySettings myCustomSettings;
public AndroidXmlPolicy(CodeStyleSettings settings,
AndroidXmlCodeStyleSettings.MySettings customSettings,
FormattingDocumentModel documentModel) {
super(settings, documentModel);
myCustomSettings = customSettings;
}
@Override
public WrapType getWrappingTypeForTagBegin(XmlTag tag) {
final PsiElement element = getNextSiblingElement(tag);
if (element instanceof XmlTag && insertLineBreakBeforeTag((XmlTag)element)) {
return WrapType.NORMAL;
}
return super.getWrappingTypeForTagBegin(tag);
}
@Override
public int getAttributesWrap() {
return myCustomSettings.WRAP_ATTRIBUTES;
}
@Override
public boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute) {
if (!myCustomSettings.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE ||
attribute.isNamespaceDeclaration()) {
return false;
}
return attribute.getParent().getAttributes().length > 1;
}
@Nullable
protected static PsiElement getPrevSiblingElement(@NotNull PsiElement element) {
final PsiElement prev = element.getPrevSibling();
ASTNode prevNode = SourceTreeToPsiMap.psiElementToTree(prev);
while (prevNode != null && FormatterUtil.containsWhiteSpacesOnly(prevNode)) {
prevNode = prevNode.getTreePrev();
}
return SourceTreeToPsiMap.treeElementToPsi(prevNode);
}
@Nullable
protected static PsiElement getNextSiblingElement(@NotNull PsiElement element) {
final PsiElement next = element.getNextSibling();
ASTNode nextNode = SourceTreeToPsiMap.psiElementToTree(next);
while (nextNode != null && FormatterUtil.containsWhiteSpacesOnly(nextNode)) {
nextNode = nextNode.getTreeNext();
}
return SourceTreeToPsiMap.treeElementToPsi(nextNode);
}
}
@@ -0,0 +1,36 @@
package org.jetbrains.android.formatter;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.PredefinedCodeStyle;
import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlPredefinedCodeStyle extends PredefinedCodeStyle {
public AndroidXmlPredefinedCodeStyle() {
super("Android", XMLLanguage.INSTANCE);
}
@Override
public void apply(CodeStyleSettings settings) {
final CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptions(XmlFileType.INSTANCE);
indentOptions.CONTINUATION_INDENT_SIZE = indentOptions.INDENT_SIZE;
XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ALIGN_ATTRIBUTES = false;
xmlSettings.XML_SPACE_INSIDE_EMPTY_TAG = true;
xmlSettings.XML_KEEP_LINE_BREAKS = false;
final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings);
androidSettings.USE_CUSTOM_SETTINGS = true;
androidSettings.LAYOUT_SETTINGS = new AndroidXmlCodeStyleSettings.LayoutSettings();
androidSettings.MANIFEST_SETTINGS = new AndroidXmlCodeStyleSettings.ManifestSettings();
androidSettings.VALUE_RESOURCE_FILE_SETTINGS = new AndroidXmlCodeStyleSettings.ValueResourceFileSettings();
androidSettings.OTHER_SETTINGS = new AndroidXmlCodeStyleSettings.OtherSettings();
}
}
@@ -0,0 +1,42 @@
package org.jetbrains.android.formatter;
/**
* @author Eugene.Kudelevsky
*/
public class ContextSpecificSettingsProviders {
public static final Provider<AndroidXmlCodeStyleSettings.LayoutSettings> LAYOUT =
new Provider<AndroidXmlCodeStyleSettings.LayoutSettings>() {
@Override
public AndroidXmlCodeStyleSettings.LayoutSettings getSettings(AndroidXmlCodeStyleSettings baseSettings) {
return baseSettings.LAYOUT_SETTINGS;
}
};
public static final Provider<AndroidXmlCodeStyleSettings.ManifestSettings> MANIFEST =
new Provider<AndroidXmlCodeStyleSettings.ManifestSettings>() {
@Override
public AndroidXmlCodeStyleSettings.ManifestSettings getSettings(AndroidXmlCodeStyleSettings baseSettings) {
return baseSettings.MANIFEST_SETTINGS;
}
};
public static final Provider<AndroidXmlCodeStyleSettings.ValueResourceFileSettings> VALUE_RESOURCE_FILE =
new Provider<AndroidXmlCodeStyleSettings.ValueResourceFileSettings>() {
@Override
public AndroidXmlCodeStyleSettings.ValueResourceFileSettings getSettings(AndroidXmlCodeStyleSettings baseSettings) {
return baseSettings.VALUE_RESOURCE_FILE_SETTINGS;
}
};
public static final Provider<AndroidXmlCodeStyleSettings.OtherSettings> OTHER =
new Provider<AndroidXmlCodeStyleSettings.OtherSettings>() {
@Override
public AndroidXmlCodeStyleSettings.OtherSettings getSettings(AndroidXmlCodeStyleSettings baseSettings) {
return baseSettings.OTHER_SETTINGS;
}
};
abstract static class Provider<T extends AndroidXmlCodeStyleSettings.MySettings> {
abstract T getSettings(AndroidXmlCodeStyleSettings baseSettings);
}
}
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.android.formatter.AndroidXmlCodeStylePanel.LayoutCodeStylePanel">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="8222b" class="com.intellij.ui.components.JBCheckBox" binding="myInsertNewLineBeforeTagCheckBox">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Insert blank line before tag"/>
</properties>
</component>
<vspacer id="29bd1">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.android.formatter.AndroidXmlCodeStylePanel.MyFileSpecificPanel">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<vspacer id="cf736">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="9d28b" binding="myAdditionalOptionsPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="230d4" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="23313"/>
<text resource-bundle="messages/ApplicationBundle" key="label.wrap.attributes"/>
</properties>
</component>
<component id="23313" class="javax.swing.JComboBox" binding="myWrapAttributesCombo">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="9dc" class="com.intellij.ui.components.JBCheckBox" binding="myInsertLineBreakBeforeFirstAttributeCheckBox">
<constraints>
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Insert line break before first attribute"/>
</properties>
</component>
<hspacer id="abe9c">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
</grid>
</form>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"
/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"
/>
</LinearLayout>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"
/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"/>
</LinearLayout>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"
/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"
/>
</LinearLayout>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"
/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME"/>
</LinearLayout>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ACTIVITY_ENTRY_NAME" />
</LinearLayout>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.untitled" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="16"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="MyActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.untitled"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:icon="@drawable/ic_launcher">
<activity
android:name="MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.untitled" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="16"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="MyActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.untitled"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:icon="@drawable/ic_launcher">
<activity
android:name="MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.untitled"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher">
<activity android:name="MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.untitled" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity
android:name="MyActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.untitled"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:icon="@drawable/ic_launcher">
<activity
android:name="MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.untitled"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="MyActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/example_preference_dependency">
<CheckBoxPreference android:key="wifi" android:title="@string/title_wifi" />
<EditTextPreference android:layout="?android:attr/preferenceLayoutChild" android:title="@string/title_wifi_settings" android:dependency="wifi" />
</PreferenceCategory>
</PreferenceScreen>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/example_preference_dependency">
<CheckBoxPreference
android:key="wifi"
android:title="@string/title_wifi" />
<EditTextPreference
android:layout="?android:attr/preferenceLayoutChild"
android:title="@string/title_wifi_settings"
android:dependency="wifi" />
</PreferenceCategory>
</PreferenceScreen>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/example_preference_dependency">
<CheckBoxPreference
android:key="wifi" android:title="@string/title_wifi" />
<EditTextPreference
android:layout="?android:attr/preferenceLayoutChild" android:title="@string/title_wifi_settings" android:dependency="wifi" />
</PreferenceCategory>
</PreferenceScreen>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/black_opaque_box" /><item android:drawable="@drawable/black_box" /><item android:drawable="@drawable/black_box" />
</selector>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/black_opaque_box" />
<item android:drawable="@drawable/black_box" />
<item android:drawable="@drawable/black_box" />
</selector>
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_window_focused="false" android:color="#ffff0000" /><item android:state_pressed="false" android:color="@color/myColor" /><item android:state_focused="true" android:color="#ffff0000" /><item android:color="<error>@color/myColo</error>" /></selector>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:color="#ffff0000" />
<item android:state_pressed="false" android:color="@color/myColor" />
<item android:state_focused="true" android:color="#ffff0000" />
<item android:color="<error>@color/myColo</error>" />
</selector>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:color="#ffff0000" />
<item android:state_pressed="false"
android:color="@color/myColor" />
<item android:state_focused="true"
android:color="#ffff0000" />
<item android:color="<error>@color/myColo</error>" />
</selector>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"><solid android:color="#00000000"/>
<stroke android:width="4dp" android:color="#99000000"
android:dashWidth="4dp" android:dashGap="2dp" /><padding android:left="7dp" android:top="7dp"
android:right="7dp" android:bottom="7dp" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#00000000" />
<stroke
android:width="4dp"
android:color="#99000000"
android:dashWidth="4dp"
android:dashGap="2dp" />
<padding
android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#00000000" />
<stroke
android:width="4dp" android:color="#99000000" android:dashWidth="4dp" android:dashGap="2dp" />
<padding
android:left="7dp" android:top="7dp" android:right="7dp" android:bottom="7dp" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">untitled</string><string name="app_name1">untitled</string>
<string-array name="myArray"><item>aba</item><item>caba</item></string-array><attr name="myAttr1"
format="boolean" /> <attr name="myAttr2"
format="boolean" />
</resources>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">untitled</string>
<string name="app_name1">untitled</string>
<string-array name="myArray">
<item>aba</item>
<item>caba</item>
</string-array>
<attr name="myAttr1" format="boolean" />
<attr name="myAttr2" format="boolean" />
</resources>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">untitled</string>
<string name="app_name1">untitled</string>
<string-array name="myArray">
<item>aba</item>
<item>caba</item>
</string-array>
<attr
name="myAttr1" format="boolean" />
<attr
name="myAttr2" format="boolean" />
</resources>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">untitled</string>
<string name="app_name1">untitled</string>
<string-array name="myArray">
<item>aba</item>
<item>caba</item>
</string-array>
<attr name="myAttr1"
format="boolean" />
<attr name="myAttr2"
format="boolean" />
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="myStyle"><item name="android:background">1</item><item name="android:color">2</item></style><string name="app_name">untitled</string><string name="app_name">untitled</string><style name="myStyle"><item name="android:background">1</item><item name="android:color">2</item></style>
</resources>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="myStyle">
<item name="android:background">1</item>
<item name="android:color">2</item>
</style>
<string name="app_name">untitled</string>
<string name="app_name">untitled</string>
<style name="myStyle">
<item name="android:background">1</item>
<item name="android:color">2</item>
</style>
</resources>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="myStyle">
<item name="android:background">1</item>
<item name="android:color">2</item>
</style>
<string name="app_name">untitled</string>
<string name="app_name">untitled</string>
<style name="myStyle">
<item name="android:background">1</item>
<item name="android:color">2</item>
</style>
</resources>
@@ -0,0 +1,229 @@
package org.jetbrains.android;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
import org.jetbrains.android.formatter.AndroidXmlCodeStyleSettings;
import org.jetbrains.android.formatter.AndroidXmlPredefinedCodeStyle;
import java.io.IOException;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidXmlFormatterTest extends AndroidTestCase {
private static final String BASE_PATH = "formatter/xml/";
private CodeStyleSettings mySettings;
public AndroidXmlFormatterTest() {
super(false);
}
public void testLayout1() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTestLayout("layout1.xml");
}
public void testLayout2() throws Exception {
doTestLayout("layout1.xml");
}
public void testLayout3() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ATTRIBUTE_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
xmlSettings.XML_KEEP_BLANK_LINES = 0;
doTestLayout("layout1.xml");
}
public void testLayout4() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ALIGN_ATTRIBUTES = true;
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.LAYOUT_SETTINGS.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = false;
androidSettings.LAYOUT_SETTINGS.INSERT_BLANK_LINE_BEFORE_TAG = false;
doTestLayout("layout1.xml");
}
public void testLayout5() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.LAYOUT_SETTINGS.WRAP_ATTRIBUTES = CommonCodeStyleSettings.DO_NOT_WRAP;
doTestLayout("layout1.xml");
}
public void testLayout6() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ALIGN_ATTRIBUTES = false;
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.LAYOUT_SETTINGS.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = false;
androidSettings.LAYOUT_SETTINGS.INSERT_BLANK_LINE_BEFORE_TAG = false;
doTestLayout("layout1.xml");
}
public void testManifest1() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTestManifest("manifest1.xml");
}
public void testManifest2() throws Exception {
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ATTRIBUTE_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
doTestManifest("manifest1.xml");
}
public void testManifest3() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ATTRIBUTE_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
xmlSettings.XML_KEEP_BLANK_LINES = 0;
doTestManifest("manifest1.xml");
}
public void testManifest4() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ALIGN_ATTRIBUTES = true;
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.MANIFEST_SETTINGS.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = false;
doTestManifest("manifest1.xml");
}
public void testManifest5() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.MANIFEST_SETTINGS.WRAP_ATTRIBUTES = CommonCodeStyleSettings.DO_NOT_WRAP;
doTestManifest("manifest1.xml");
}
public void testManifest6() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.MANIFEST_SETTINGS.GROUP_TAGS_WITH_SAME_NAME = false;
doTestManifest("manifest1.xml");
}
public void testManifest7() throws Exception {
final XmlCodeStyleSettings xmlSettings = mySettings.getCustomSettings(XmlCodeStyleSettings.class);
xmlSettings.XML_ATTRIBUTE_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
doTestManifest("manifest1.xml");
}
public void testValues1() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTestValues("values1.xml");
}
public void testValues2() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.VALUE_RESOURCE_FILE_SETTINGS.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = true;
doTestValues("values1.xml");
}
public void testValues3() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.VALUE_RESOURCE_FILE_SETTINGS.WRAP_ATTRIBUTES = CommonCodeStyleSettings.WRAP_ALWAYS;
doTestValues("values1.xml");
}
public void testValues4() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTestValues("values4.xml");
}
public void testValues5() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.VALUE_RESOURCE_FILE_SETTINGS.INSERT_LINE_BREAKS_AROUND_STYLE = false;
doTestValues("values4.xml");
}
public void testSelector1() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTest("selector1.xml", "res/drawable/selector.xml");
}
public void testSelector2() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTest("selector2.xml", "res/color/selector.xml");
}
public void testSelector3() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.VALUE_RESOURCE_FILE_SETTINGS.WRAP_ATTRIBUTES = CommonCodeStyleSettings.WRAP_ALWAYS;
doTest("selector2.xml", "res/color/selector.xml");
}
public void testShapeDrawable1() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTest("shapeDrawable1.xml", "res/drawable/drawable.xml");
}
public void testShapeDrawable2() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.OTHER_SETTINGS.WRAP_ATTRIBUTES = CommonCodeStyleSettings.DO_NOT_WRAP;
doTest("shapeDrawable1.xml", "res/drawable/drawable.xml");
}
public void testPreferences1() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
doTest("preferences1.xml", "res/xml/preferences.xml");
}
public void testPreferences2() throws Exception {
new AndroidXmlPredefinedCodeStyle().apply(mySettings);
final AndroidXmlCodeStyleSettings androidSettings = mySettings.getCustomSettings(AndroidXmlCodeStyleSettings.class);
androidSettings.OTHER_SETTINGS.WRAP_ATTRIBUTES = CommonCodeStyleSettings.DO_NOT_WRAP;
doTest("preferences1.xml", "res/xml/preferences.xml");
}
private void doTestLayout(String fileName) throws IOException {
createManifest();
doTest(fileName, "res/layout/layout.xml");
}
private void doTestManifest(String fileName) {
doTest(fileName, "AndroidManifest.xml");
}
private void doTestValues(String fileName) {
doTest(fileName, "res/values/values.xml");
}
private void doTest(String fileName, String dstFileName) {
final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + fileName, dstFileName);
myFixture.configureFromExistingVirtualFile(f);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
CodeStyleManager.getInstance(getProject()).reformat(myFixture.getFile());
}
});
myFixture.checkResultByFile(BASE_PATH + getTestName(true) + "_after.xml");
}
@Override
public void setUp() throws Exception {
super.setUp();
mySettings = CodeStyleSettingsManager.getSettings(getProject()).clone();
CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(mySettings);
}
@Override
public void tearDown() throws Exception {
CodeStyleSettingsManager.getInstance(getProject()).dropTemporarySettings();
super.tearDown();
}
}
@@ -15,10 +15,10 @@
*/
package com.intellij.application.options;
import com.intellij.lang.Language;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import org.jetbrains.annotations.Nullable;
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
/**
* @author Rustam Vishnyakov
@@ -32,5 +32,11 @@ public class XmlCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
protected void initTabs(CodeStyleSettings settings) {
addIndentOptionsTab(settings);
addTab(new CodeStyleXmlPanel(settings));
for (CodeStyleSettingsProvider provider : Extensions.getExtensions(CodeStyleSettingsProvider.EXTENSION_POINT_NAME)) {
if (provider.getLanguage() == XMLLanguage.INSTANCE && !provider.hasSettingsPage()) {
createTab(provider);
}
}
}
}
@@ -24,6 +24,7 @@ import com.intellij.psi.TokenType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlTag;
@@ -88,6 +89,16 @@ public class HtmlPolicy extends XmlFormattingPolicy {
return checkName(xmlTag, mySettings.HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE);
}
@Override
public boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute) {
return false;
}
@Override
public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
return false;
}
private boolean containsWhiteSpacesOnly(final ASTNode node) {
if (node == null) return false;
if (node.getElementType() == TokenType.WHITE_SPACE) return true;
@@ -18,10 +18,13 @@ package com.intellij.psi.formatter.xml;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.formatter.common.AbstractBlock;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTokenType;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -109,7 +112,15 @@ public class SyntheticBlock extends AbstractSyntheticBlock implements Block, Rea
}
if (type2 == XmlElementType.XML_ATTRIBUTE) {
return Spacing.createSpacing(1, 1, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
int minLineFeeds = 0;
if (type1 == XmlTokenType.XML_NAME) {
final PsiElement psi2 = node2.getPsi();
minLineFeeds = psi2 instanceof XmlAttribute &&
myXmlFormattingPolicy.insertLineBreakBeforeFirstAttribute((XmlAttribute)psi2)
? 1 : 0;
}
return Spacing.createSpacing(1, 1, minLineFeeds, myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines());
}
if (((AbstractXmlBlock)child1).isTextElement() && ((AbstractXmlBlock)child2).isTextElement()) {
@@ -25,6 +25,7 @@ import com.intellij.lang.LanguageFormatting;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.HashMap;
@@ -87,6 +88,10 @@ public abstract class XmlFormattingPolicy {
public abstract boolean insertLineBreakBeforeTag(XmlTag xmlTag);
public abstract boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute);
public abstract boolean insertLineBreakAfterTagBegin(XmlTag tag);
public abstract boolean removeLineBreakBeforeTag(XmlTag xmlTag);
public abstract boolean keepWhiteSpacesInsideTag(XmlTag tag);
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlText;
@@ -42,6 +43,16 @@ public class XmlPolicy extends XmlFormattingPolicy{
return false;
}
@Override
public boolean insertLineBreakBeforeFirstAttribute(XmlAttribute attribute) {
return false;
}
@Override
public boolean insertLineBreakAfterTagBegin(XmlTag tag) {
return false;
}
public boolean removeLineBreakBeforeTag(final XmlTag xmlTag) {
return false;
}
@@ -279,11 +279,13 @@ public class XmlTagBlock extends AbstractXmlBlock{
}
return Spacing.createSpacing(0, 0, 0, true, myXmlFormattingPolicy.getKeepBlankLines());
} else if (syntheticBlock1.isTagDescription() && syntheticBlock2.startsWithTag()) {
return Spacing.createSpacing(0, 0, 0, true, myXmlFormattingPolicy.getKeepBlankLines());
return Spacing.createSpacing(0, 0, myXmlFormattingPolicy.insertLineBreakAfterTagBegin(getTag()) ? 2 : 0,
true, myXmlFormattingPolicy.getKeepBlankLines());
} else if (syntheticBlock1.insertLineFeedAfter()) {
return Spacing.createSpacing(0,0,1,true,myXmlFormattingPolicy.getKeepBlankLines());
} else if (syntheticBlock1.endsWithTag() && syntheticBlock2.isTagDescription()) {
return Spacing.createSpacing(0, 0, 0, true, myXmlFormattingPolicy.getKeepBlankLines());
return Spacing.createSpacing(0, 0, myXmlFormattingPolicy.insertLineBreakAfterTagBegin(getTag()) ? 2 : 0,
true, myXmlFormattingPolicy.getKeepBlankLines());
} else {
return createDefaultSpace(true, true);
}