Merge branch 'master' of git@git.labs.intellij.net:idea/community
[idea/community.git] / platform / lang-api / src / com / intellij / psi / codeStyle / CodeStyleSettings.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.psi.codeStyle;
17
18 import com.intellij.openapi.extensions.Extensions;
19 import com.intellij.openapi.fileTypes.FileType;
20 import com.intellij.openapi.fileTypes.FileTypeManager;
21 import com.intellij.openapi.fileTypes.FileTypes;
22 import com.intellij.openapi.util.*;
23 import com.intellij.openapi.util.text.StringUtil;
24 import com.intellij.openapi.vfs.VirtualFile;
25 import com.intellij.util.SystemProperties;
26 import com.intellij.util.containers.ClassMap;
27 import org.jdom.Element;
28 import org.jetbrains.annotations.NonNls;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.TestOnly;
31
32 import javax.swing.*;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.Modifier;
35 import java.util.*;
36
37 public class CodeStyleSettings implements Cloneable, JDOMExternalizable {
38   private final ClassMap<CustomCodeStyleSettings> myCustomSettings = new ClassMap<CustomCodeStyleSettings>();
39   @NonNls private static final String ADDITIONAL_INDENT_OPTIONS = "ADDITIONAL_INDENT_OPTIONS";
40   @NonNls private static final String FILETYPE = "fileType";
41
42   public CodeStyleSettings() {
43     this(true);
44   }
45
46   public CodeStyleSettings(boolean loadExtensions) {
47     initTypeToName();
48     initImportsByDefault();
49
50     if (loadExtensions) {
51       final CodeStyleSettingsProvider[] codeStyleSettingsProviders = Extensions.getExtensions(CodeStyleSettingsProvider.EXTENSION_POINT_NAME);
52       for (final CodeStyleSettingsProvider provider : codeStyleSettingsProviders) {
53         addCustomSettings(provider.createCustomSettings(this));
54       }
55     }
56   }
57
58   private void initImportsByDefault() {
59     PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false, "java.awt", false));
60     PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false,"javax.swing", false));
61     IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
62     IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
63     IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "javax", true));
64     IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "java", true));
65     IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
66     IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
67   }
68
69   private void initTypeToName() {
70     initGeneralLocalVariable(PARAMETER_TYPE_TO_NAME);
71     initGeneralLocalVariable(LOCAL_VARIABLE_TYPE_TO_NAME);
72     PARAMETER_TYPE_TO_NAME.addPair("*Exception", "e");
73   }
74
75   private static void initGeneralLocalVariable(@NonNls TypeToNameMap map) {
76     map.addPair("int", "i");
77     map.addPair("byte", "b");
78     map.addPair("char", "c");
79     map.addPair("long", "l");
80     map.addPair("short", "i");
81     map.addPair("boolean", "b");
82     map.addPair("double", "v");
83     map.addPair("float", "v");
84     map.addPair("java.lang.Object", "o");
85     map.addPair("java.lang.String", "s");
86   }
87
88   public void setParentSettings(CodeStyleSettings parent) {
89     myParentSettings = parent;
90   }
91
92   public CodeStyleSettings getParentSettings() {
93     return myParentSettings;
94   }
95
96   private void addCustomSettings(CustomCodeStyleSettings settings) {
97     if (settings != null) {
98       myCustomSettings.put(settings.getClass(), settings);
99     }
100   }
101
102   public <T extends CustomCodeStyleSettings> T getCustomSettings(Class<T> aClass) {
103     return (T)myCustomSettings.get(aClass);
104   }
105
106   public CodeStyleSettings clone() {
107     CodeStyleSettings clone = new CodeStyleSettings();
108     clone.copyFrom(this);
109     return clone;
110   }
111
112   private void copyCustomSettingsFrom(CodeStyleSettings from) {
113     assert from != this;
114     myCustomSettings.clear();
115     for (final CustomCodeStyleSettings settings : from.myCustomSettings.values()) {
116       addCustomSettings((CustomCodeStyleSettings) settings.clone());
117     }
118
119     FIELD_TYPE_TO_NAME.copyFrom(from.FIELD_TYPE_TO_NAME);
120     STATIC_FIELD_TYPE_TO_NAME.copyFrom(from.STATIC_FIELD_TYPE_TO_NAME);
121     PARAMETER_TYPE_TO_NAME.copyFrom(from.PARAMETER_TYPE_TO_NAME);
122     LOCAL_VARIABLE_TYPE_TO_NAME.copyFrom(from.LOCAL_VARIABLE_TYPE_TO_NAME);
123
124     PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(from.PACKAGES_TO_USE_IMPORT_ON_DEMAND);
125     IMPORT_LAYOUT_TABLE.copyFrom(from.IMPORT_LAYOUT_TABLE);
126
127     OTHER_INDENT_OPTIONS.copyFrom(from.OTHER_INDENT_OPTIONS);
128
129     myAdditionalIndentOptions.clear();
130     for(Map.Entry<FileType, IndentOptions> optionEntry: from.myAdditionalIndentOptions.entrySet()) {
131       IndentOptions options = optionEntry.getValue();
132       myAdditionalIndentOptions.put(optionEntry.getKey(),(IndentOptions)options.clone());
133     }
134   }
135
136   public void copyFrom(CodeStyleSettings from) {
137     copyPublicFields(from, this);
138
139     this.copyCustomSettingsFrom(from);
140   }
141
142   private static void copyPublicFields(Object from, Object to) {
143     assert from != to;
144     Field[] fields = to.getClass().getDeclaredFields();
145     for (Field field : fields) {
146       if (isPublic(field) && !isFinal(field)) {
147         try {
148           copyFieldValue(from, to, field);
149         }
150         catch (Exception e) {
151           throw new RuntimeException(e);
152         }
153       }
154     }
155   }
156
157   private static void copyFieldValue(final Object from, Object to, final Field field)
158     throws IllegalAccessException {
159     Class<?> fieldType = field.getType();
160     if (fieldType.isPrimitive()) {
161       field.set(to, field.get(from));
162     }
163     else if (fieldType.equals(String.class)) {
164       field.set(to, field.get(from));
165     }
166     else {
167       System.out.println("Field not copied " + field.getName());
168     }
169   }
170
171   private static boolean isPublic(final Field field) {
172     return (field.getModifiers() & Modifier.PUBLIC) != 0;
173   }
174
175   private static boolean isFinal(final Field field) {
176     return (field.getModifiers() & Modifier.FINAL) != 0;
177   }
178
179 //----------------- GENERAL --------------------
180
181   public boolean LINE_COMMENT_AT_FIRST_COLUMN = true;
182   public boolean BLOCK_COMMENT_AT_FIRST_COLUMN = true;
183
184   public boolean KEEP_LINE_BREAKS = true;
185
186   /**
187    * Controls END_OF_LINE_COMMENT's and C_STYLE_COMMENT's
188    */
189   public boolean KEEP_FIRST_COLUMN_COMMENT = true;
190   public boolean INSERT_FIRST_SPACE_IN_LINE = true;
191
192   public boolean USE_SAME_INDENTS = false;
193
194   public static class IndentOptions implements JDOMExternalizable, Cloneable {
195     public int INDENT_SIZE = 4;
196     public int CONTINUATION_INDENT_SIZE = 8;
197     public int TAB_SIZE = 4;
198     public boolean USE_TAB_CHARACTER = false;
199     public boolean SMART_TABS = false;
200     public int LABEL_INDENT_SIZE = 0;
201     public boolean LABEL_INDENT_ABSOLUTE = false;
202
203     public void readExternal(Element element) throws InvalidDataException {
204       DefaultJDOMExternalizer.readExternal(this, element);
205     }
206
207     public void writeExternal(Element element) throws WriteExternalException {
208       DefaultJDOMExternalizer.writeExternal(this, element);
209     }
210
211     public Object clone() {
212       try {
213         return super.clone();
214       }
215       catch (CloneNotSupportedException e) {
216         // Cannot happen
217         throw new RuntimeException(e);
218       }
219     }
220
221     @Override
222     public boolean equals(Object o) {
223       if (this == o) return true;
224       if (o == null || getClass() != o.getClass()) return false;
225
226       IndentOptions that = (IndentOptions)o;
227
228       if (CONTINUATION_INDENT_SIZE != that.CONTINUATION_INDENT_SIZE) return false;
229       if (INDENT_SIZE != that.INDENT_SIZE) return false;
230       if (LABEL_INDENT_ABSOLUTE != that.LABEL_INDENT_ABSOLUTE) return false;
231       if (LABEL_INDENT_SIZE != that.LABEL_INDENT_SIZE) return false;
232       if (SMART_TABS != that.SMART_TABS) return false;
233       if (TAB_SIZE != that.TAB_SIZE) return false;
234       if (USE_TAB_CHARACTER != that.USE_TAB_CHARACTER) return false;
235
236       return true;
237     }
238
239     @Override
240     public int hashCode() {
241       int result = INDENT_SIZE;
242       result = 31 * result + CONTINUATION_INDENT_SIZE;
243       result = 31 * result + TAB_SIZE;
244       result = 31 * result + (USE_TAB_CHARACTER ? 1 : 0);
245       result = 31 * result + (SMART_TABS ? 1 : 0);
246       result = 31 * result + LABEL_INDENT_SIZE;
247       result = 31 * result + (LABEL_INDENT_ABSOLUTE ? 1 : 0);
248       return result;
249     }
250
251     public void copyFrom(IndentOptions other) {
252       copyPublicFields(other, this);
253     }
254   }
255
256   @Deprecated
257   public final IndentOptions JAVA_INDENT_OPTIONS = new IndentOptions();
258   @Deprecated
259   public final IndentOptions JSP_INDENT_OPTIONS = new IndentOptions();
260   @Deprecated
261   public final IndentOptions XML_INDENT_OPTIONS = new IndentOptions();
262
263   public final IndentOptions OTHER_INDENT_OPTIONS = new IndentOptions();
264
265   private final Map<FileType,IndentOptions> myAdditionalIndentOptions = new LinkedHashMap<FileType, IndentOptions>();
266
267   private static final String ourSystemLineSeparator = SystemProperties.getLineSeparator();
268
269   /**
270    * Line separator. It can be null if choosen line separator is "System-dependent"!
271    */
272   public String LINE_SEPARATOR;
273
274   /**
275    * @return line separator. If choosen line separator is "System-dependent" method returns default separator for this OS.
276    */
277   public String getLineSeparator() {
278     return LINE_SEPARATOR != null ? LINE_SEPARATOR : ourSystemLineSeparator;
279   }
280
281   /**
282    * Keep "if (..) ...;" (also while, for)
283    * Does not control "if (..) { .. }"
284    */
285   public boolean KEEP_CONTROL_STATEMENT_IN_ONE_LINE = true;
286
287 //----------------- BRACES & INDENTS --------------------
288
289   /**
290    * <PRE>
291    * 1.
292    * if (..) {
293    * body;
294    * }
295    * 2.
296    * if (..)
297    * {
298    * body;
299    * }
300    * 3.
301    * if (..)
302    * {
303    * body;
304    * }
305    * 4.
306    * if (..)
307    * {
308    * body;
309    * }
310    * 5.
311    * if (long-condition-1 &&
312    * long-condition-2)
313    * {
314    * body;
315    * }
316    * if (short-condition) {
317    * body;
318    * }
319    * </PRE>
320    */
321
322   public static final int END_OF_LINE = 1;
323   public static final int NEXT_LINE = 2;
324   public static final int NEXT_LINE_SHIFTED = 3;
325   public static final int NEXT_LINE_SHIFTED2 = 4;
326   public static final int NEXT_LINE_IF_WRAPPED = 5;
327
328   public int BRACE_STYLE = 1;
329   public int CLASS_BRACE_STYLE = 1;
330   public int METHOD_BRACE_STYLE = 1;
331
332   public boolean DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS = false;
333
334   /**
335    * <PRE>
336    * "}
337    * else"
338    * or
339    * "} else"
340    * </PRE>
341    */
342   public boolean ELSE_ON_NEW_LINE = false;
343
344   /**
345    * <PRE>
346    * "}
347    * while"
348    * or
349    * "} while"
350    * </PRE>
351    */
352   public boolean WHILE_ON_NEW_LINE = false;
353
354   /**
355    * <PRE>
356    * "}
357    * catch"
358    * or
359    * "} catch"
360    * </PRE>
361    */
362   public boolean CATCH_ON_NEW_LINE = false;
363
364   /**
365    * <PRE>
366    * "}
367    * finally"
368    * or
369    * "} finally"
370    * </PRE>
371    */
372   public boolean FINALLY_ON_NEW_LINE = false;
373
374   public boolean INDENT_CASE_FROM_SWITCH = true;
375
376   public boolean SPECIAL_ELSE_IF_TREATMENT = true;
377
378   public boolean ALIGN_MULTILINE_PARAMETERS = true;
379   public boolean ALIGN_MULTILINE_PARAMETERS_IN_CALLS = false;
380   public boolean ALIGN_MULTILINE_FOR = true;
381   public boolean INDENT_WHEN_CASES = true;
382
383   public boolean ALIGN_MULTILINE_BINARY_OPERATION = false;
384   public boolean ALIGN_MULTILINE_ASSIGNMENT = false;
385   public boolean ALIGN_MULTILINE_TERNARY_OPERATION = false;
386   public boolean ALIGN_MULTILINE_THROWS_LIST = false;
387   public boolean ALIGN_MULTILINE_EXTENDS_LIST = false;
388   public boolean ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION = false;
389
390   public boolean ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION = false;
391
392 //----------------- Group alignments ---------------
393
394   public boolean ALIGN_GROUP_FIELD_DECLARATIONS = false;
395
396 //----------------- BLANK LINES --------------------
397
398   /**
399    * Keep up to this amount of blank lines between declarations
400    */
401   public int KEEP_BLANK_LINES_IN_DECLARATIONS = 2;
402
403   /**
404    * Keep up to this amount of blank lines in code
405    */
406   public int KEEP_BLANK_LINES_IN_CODE = 2;
407
408   public int KEEP_BLANK_LINES_BEFORE_RBRACE = 2;
409
410   public int BLANK_LINES_BEFORE_PACKAGE = 0;
411   public int BLANK_LINES_AFTER_PACKAGE = 1;
412   public int BLANK_LINES_BEFORE_IMPORTS = 1;
413   public int BLANK_LINES_AFTER_IMPORTS = 1;
414
415   public int BLANK_LINES_AROUND_CLASS = 1;
416   public int BLANK_LINES_AROUND_FIELD = 0;
417   public int BLANK_LINES_AROUND_METHOD = 1;
418
419   public int BLANK_LINES_AROUND_FIELD_IN_INTERFACE = 0;
420   public int BLANK_LINES_AROUND_METHOD_IN_INTERFACE = 1;
421
422
423   public int BLANK_LINES_AFTER_CLASS_HEADER = 0;
424   //public int BLANK_LINES_BETWEEN_CASE_BLOCKS;
425
426 //----------------- SPACES --------------------
427
428   /**
429    * Controls =, +=, -=, etc
430    */
431   public boolean SPACE_AROUND_ASSIGNMENT_OPERATORS = true;
432
433   /**
434    * Controls &&, ||
435    */
436   public boolean SPACE_AROUND_LOGICAL_OPERATORS = true;
437
438   /**
439    * Controls ==, !=
440    */
441   public boolean SPACE_AROUND_EQUALITY_OPERATORS = true;
442
443   /**
444    * Controls <, >, <=, >=
445    */
446   public boolean SPACE_AROUND_RELATIONAL_OPERATORS = true;
447
448   /**
449    * Controls &, |, ^
450    */
451   public boolean SPACE_AROUND_BITWISE_OPERATORS = true;
452
453   /**
454    * Controls +, -
455    */
456   public boolean SPACE_AROUND_ADDITIVE_OPERATORS = true;
457
458   /**
459    * Controls *, /, %
460    */
461   public boolean SPACE_AROUND_MULTIPLICATIVE_OPERATORS = true;
462
463   /**
464    * Controls <<. >>, >>>
465    */
466   public boolean SPACE_AROUND_SHIFT_OPERATORS = true;
467
468   public boolean SPACE_AFTER_COMMA = true;
469   public boolean SPACE_BEFORE_COMMA = false;
470   public boolean SPACE_AFTER_SEMICOLON = true; // in for-statement
471   public boolean SPACE_BEFORE_SEMICOLON = false; // in for-statement
472
473   /**
474    * "( expr )"
475    * or
476    * "(expr)"
477    */
478   public boolean SPACE_WITHIN_PARENTHESES = false;
479
480   /**
481    * "f( expr )"
482    * or
483    * "f(expr)"
484    */
485   public boolean SPACE_WITHIN_METHOD_CALL_PARENTHESES = false;
486
487   /**
488    * "void f( int param )"
489    * or
490    * "void f(int param)"
491    */
492   public boolean SPACE_WITHIN_METHOD_PARENTHESES = false;
493
494   /**
495    * "if( expr )"
496    * or
497    * "if(expr)"
498    */
499   public boolean SPACE_WITHIN_IF_PARENTHESES = false;
500
501   /**
502    * "while( expr )"
503    * or
504    * "while(expr)"
505    */
506   public boolean SPACE_WITHIN_WHILE_PARENTHESES = false;
507
508   /**
509    * "for( int i = 0; i < 10; i++ )"
510    * or
511    * "for(int i = 0; i < 10; i++)"
512    */
513   public boolean SPACE_WITHIN_FOR_PARENTHESES = false;
514
515   /**
516    * "catch( Exception e )"
517    * or
518    * "catch(Exception e)"
519    */
520   public boolean SPACE_WITHIN_CATCH_PARENTHESES = false;
521
522   /**
523    * "switch( expr )"
524    * or
525    * "switch(expr)"
526    */
527   public boolean SPACE_WITHIN_SWITCH_PARENTHESES = false;
528
529   /**
530    * "synchronized( expr )"
531    * or
532    * "synchronized(expr)"
533    */
534   public boolean SPACE_WITHIN_SYNCHRONIZED_PARENTHESES = false;
535
536   /**
537    * "( Type )expr"
538    * or
539    * "(Type)expr"
540    */
541   public boolean SPACE_WITHIN_CAST_PARENTHESES = false;
542
543   /**
544    * "[ expr ]"
545    * or
546    * "[expr]"
547    */
548   public boolean SPACE_WITHIN_BRACKETS = false;
549
550   /**
551    * "int X[] { 1, 3, 5 }"
552    * or
553    * "int X[] {1, 3, 5}"
554    */
555   public boolean SPACE_WITHIN_ARRAY_INITIALIZER_BRACES = false;
556
557   public boolean SPACE_AFTER_TYPE_CAST = true;
558
559   /**
560    * "f (x)"
561    * or
562    * "f(x)"
563    */
564   public boolean SPACE_BEFORE_METHOD_CALL_PARENTHESES = false;
565
566   /**
567    * "void f (int param)"
568    * or
569    * "void f(int param)"
570    */
571   public boolean SPACE_BEFORE_METHOD_PARENTHESES = false;
572
573   /**
574    * "if (...)"
575    * or
576    * "if(...)"
577    */
578   public boolean SPACE_BEFORE_IF_PARENTHESES = true;
579
580   /**
581    * "while (...)"
582    * or
583    * "while(...)"
584    */
585   public boolean SPACE_BEFORE_WHILE_PARENTHESES = true;
586
587   /**
588    * "for (...)"
589    * or
590    * "for(...)"
591    */
592   public boolean SPACE_BEFORE_FOR_PARENTHESES = true;
593
594   /**
595    * "catch (...)"
596    * or
597    * "catch(...)"
598    */
599   public boolean SPACE_BEFORE_CATCH_PARENTHESES = true;
600
601   /**
602    * "switch (...)"
603    * or
604    * "switch(...)"
605    */
606   public boolean SPACE_BEFORE_SWITCH_PARENTHESES = true;
607
608   /**
609    * "synchronized (...)"
610    * or
611    * "synchronized(...)"
612    */
613   public boolean SPACE_BEFORE_SYNCHRONIZED_PARENTHESES = true;
614
615   /**
616    * "class A {"
617    * or
618    * "class A{"
619    */
620   public boolean SPACE_BEFORE_CLASS_LBRACE = true;
621
622   /**
623    * "void f() {"
624    * or
625    * "void f(){"
626    */
627   public boolean SPACE_BEFORE_METHOD_LBRACE = true;
628
629   /**
630    * "if (...) {"
631    * or
632    * "if (...){"
633    */
634   public boolean SPACE_BEFORE_IF_LBRACE = true;
635
636   /**
637    * "else {"
638    * or
639    * "else{"
640    */
641   public boolean SPACE_BEFORE_ELSE_LBRACE = true;
642
643   /**
644    * "while (...) {"
645    * or
646    * "while (...){"
647    */
648   public boolean SPACE_BEFORE_WHILE_LBRACE = true;
649
650   /**
651    * "for (...) {"
652    * or
653    * "for (...){"
654    */
655   public boolean SPACE_BEFORE_FOR_LBRACE = true;
656
657   /**
658    * "do {"
659    * or
660    * "do{"
661    */
662   public boolean SPACE_BEFORE_DO_LBRACE = true;
663
664   /**
665    * "switch (...) {"
666    * or
667    * "switch (...){"
668    */
669   public boolean SPACE_BEFORE_SWITCH_LBRACE = true;
670
671   /**
672    * "try {"
673    * or
674    * "try{"
675    */
676   public boolean SPACE_BEFORE_TRY_LBRACE = true;
677
678   /**
679    * "catch (...) {"
680    * or
681    * "catch (...){"
682    */
683   public boolean SPACE_BEFORE_CATCH_LBRACE = true;
684
685   /**
686    * "finally {"
687    * or
688    * "finally{"
689    */
690   public boolean SPACE_BEFORE_FINALLY_LBRACE = true;
691
692   /**
693    * "synchronized (...) {"
694    * or
695    * "synchronized (...){"
696    */
697   public boolean SPACE_BEFORE_SYNCHRONIZED_LBRACE = true;
698
699   /**
700    * "new int[] {"
701    * or
702    * "new int[]{"
703    */
704   public boolean SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE = false;
705
706   public boolean SPACE_BEFORE_QUEST = true;
707   public boolean SPACE_AFTER_QUEST = true;
708   public boolean SPACE_BEFORE_COLON = true;
709   public boolean SPACE_AFTER_COLON = true;
710   public boolean SPACE_BEFORE_TYPE_PARAMETER_LIST = false;
711
712 //----------------- NAMING CONVENTIONS --------------------
713
714   public String FIELD_NAME_PREFIX = "";
715   public String STATIC_FIELD_NAME_PREFIX = "";
716   public String PARAMETER_NAME_PREFIX = "";
717   public String LOCAL_VARIABLE_NAME_PREFIX = "";
718
719   public String FIELD_NAME_SUFFIX = "";
720   public String STATIC_FIELD_NAME_SUFFIX = "";
721   public String PARAMETER_NAME_SUFFIX = "";
722   public String LOCAL_VARIABLE_NAME_SUFFIX = "";
723
724   public boolean PREFER_LONGER_NAMES = true;
725
726   public final TypeToNameMap FIELD_TYPE_TO_NAME = new TypeToNameMap();
727   public final TypeToNameMap STATIC_FIELD_TYPE_TO_NAME = new TypeToNameMap();
728   @NonNls public final TypeToNameMap PARAMETER_TYPE_TO_NAME = new TypeToNameMap();
729   public final TypeToNameMap LOCAL_VARIABLE_TYPE_TO_NAME = new TypeToNameMap();
730
731 //----------------- 'final' modifier settings -------
732   public boolean GENERATE_FINAL_LOCALS = false;
733   public boolean GENERATE_FINAL_PARAMETERS = false;
734
735 //----------------- annotations ----------------
736   public boolean USE_EXTERNAL_ANNOTATIONS = false;
737   public boolean INSERT_OVERRIDE_ANNOTATION = true;
738
739 //----------------- IMPORTS --------------------
740
741   public boolean LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
742   public boolean USE_FQ_CLASS_NAMES = false;
743   public boolean USE_FQ_CLASS_NAMES_IN_JAVADOC = true;
744   public boolean USE_SINGLE_CLASS_IMPORTS = true;
745   public boolean INSERT_INNER_CLASS_IMPORTS = false;
746   public int CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 5;
747   public int NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = 3;
748   public final PackageEntryTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageEntryTable();
749   public final PackageEntryTable IMPORT_LAYOUT_TABLE = new PackageEntryTable();
750   public boolean OPTIMIZE_IMPORTS_ON_THE_FLY = false;
751   public boolean ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = false;
752
753 //----------------- ORDER OF MEMBERS ------------------
754
755   public int FIELDS_ORDER_WEIGHT = 1;
756   public int CONSTRUCTORS_ORDER_WEIGHT = 2;
757   public int METHODS_ORDER_WEIGHT = 3;
758   public int INNER_CLASSES_ORDER_WEIGHT = 4;
759
760 //----------------- WRAPPING ---------------------------
761   public int RIGHT_MARGIN = 120;
762
763   public static final int DO_NOT_WRAP = 0x00;
764   public static final int WRAP_AS_NEEDED = 0x01;
765   public static final int WRAP_ALWAYS = 0x02;
766   public static final int WRAP_ON_EVERY_ITEM = 0x04;
767
768   public int CALL_PARAMETERS_WRAP = DO_NOT_WRAP;
769   public boolean PREFER_PARAMETERS_WRAP = false;
770   public boolean CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = false;
771   public boolean CALL_PARAMETERS_RPAREN_ON_NEXT_LINE = false;
772
773   public int METHOD_PARAMETERS_WRAP = DO_NOT_WRAP;
774   public boolean METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE = false;
775   public boolean METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE = false;
776
777   public int EXTENDS_LIST_WRAP = DO_NOT_WRAP;
778   public int THROWS_LIST_WRAP = DO_NOT_WRAP;
779
780   public int EXTENDS_KEYWORD_WRAP = DO_NOT_WRAP;
781   public int THROWS_KEYWORD_WRAP = DO_NOT_WRAP;
782
783   public int METHOD_CALL_CHAIN_WRAP = DO_NOT_WRAP;
784
785   public boolean PARENTHESES_EXPRESSION_LPAREN_WRAP = false;
786   public boolean PARENTHESES_EXPRESSION_RPAREN_WRAP = false;
787
788   public int BINARY_OPERATION_WRAP = DO_NOT_WRAP;
789   public boolean BINARY_OPERATION_SIGN_ON_NEXT_LINE = false;
790
791   public int TERNARY_OPERATION_WRAP = DO_NOT_WRAP;
792   public boolean TERNARY_OPERATION_SIGNS_ON_NEXT_LINE = false;
793
794   public boolean MODIFIER_LIST_WRAP = false;
795
796   public boolean KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false;
797   public boolean KEEP_SIMPLE_METHODS_IN_ONE_LINE = false;
798
799   public int FOR_STATEMENT_WRAP = DO_NOT_WRAP;
800   public boolean FOR_STATEMENT_LPAREN_ON_NEXT_LINE = false;
801   public boolean FOR_STATEMENT_RPAREN_ON_NEXT_LINE = false;
802
803   public int ARRAY_INITIALIZER_WRAP = DO_NOT_WRAP;
804   public boolean ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = false;
805   public boolean ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE = false;
806
807   public int ASSIGNMENT_WRAP = DO_NOT_WRAP;
808   public boolean PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE = false;
809
810   public int LABELED_STATEMENT_WRAP = WRAP_ALWAYS;
811
812   public boolean WRAP_COMMENTS = false;
813
814   public int ASSERT_STATEMENT_WRAP = DO_NOT_WRAP;
815   public boolean ASSERT_STATEMENT_COLON_ON_NEXT_LINE = false;
816
817 // BRACE FORCING
818   public static final int DO_NOT_FORCE = 0x00;
819   public static final int FORCE_BRACES_IF_MULTILINE = 0x01;
820   public static final int FORCE_BRACES_ALWAYS = 0x03;
821
822   public int IF_BRACE_FORCE = DO_NOT_FORCE;
823   public int DOWHILE_BRACE_FORCE = DO_NOT_FORCE;
824   public int WHILE_BRACE_FORCE = DO_NOT_FORCE;
825   public int FOR_BRACE_FORCE = DO_NOT_FORCE;
826
827 //----------------- EJB NAMING CONVENTIONS -------------
828 /**
829  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
830  */
831   @NonNls public String ENTITY_EB_PREFIX = "";         //EntityBean EJB Class name prefix
832   /**
833  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
834  */
835   @NonNls public String ENTITY_EB_SUFFIX = "Bean";     //EntityBean EJB Class name suffix
836   /**
837  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
838  */
839   @NonNls public String ENTITY_HI_PREFIX = "";         //EntityBean Home interface name prefix
840   /**
841  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
842  */
843   @NonNls public String ENTITY_HI_SUFFIX = "Home";     //EntityBean Home interface name suffix
844   /**
845  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
846  */
847   @NonNls public String ENTITY_RI_PREFIX = "";         //EntityBean Remote interface name prefix
848   /**
849  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
850  */
851   @NonNls public String ENTITY_RI_SUFFIX = "";         //EntityBean Remote interface name prefix
852   /**
853  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
854  */
855   @NonNls public String ENTITY_LHI_PREFIX = "Local";   //EntityBean local Home interface name prefix
856   /**
857  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
858  */
859   @NonNls public String ENTITY_LHI_SUFFIX = "Home";    //EntityBean local Home interface name suffix
860   /**
861  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
862  */
863   @NonNls public String ENTITY_LI_PREFIX = "Local";    //EntityBean local interface name prefix
864   /**
865  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
866  */
867   @NonNls public String ENTITY_LI_SUFFIX = "";         //EntityBean local interface name suffix
868   /**
869  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
870  */
871   @NonNls public String ENTITY_DD_PREFIX = "";         //EntityBean deployment descriptor name prefix
872   /**
873  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
874  */
875   @NonNls public String ENTITY_DD_SUFFIX = "EJB";      //EntityBean deployment descriptor name suffix
876   /**
877  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
878  */
879   @NonNls public String ENTITY_VO_PREFIX = "";
880   /**
881  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
882  */
883   @NonNls public String ENTITY_VO_SUFFIX = "VO";
884   /**
885  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
886  */
887   @NonNls public String ENTITY_PK_CLASS = "java.lang.String";
888
889   /**
890  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
891  */
892   @NonNls public String SESSION_EB_PREFIX = "";        //SessionBean EJB Class name prefix
893   /**
894  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
895  */
896   @NonNls public String SESSION_EB_SUFFIX = "Bean";    //SessionBean EJB Class name suffix
897   /**
898  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
899  */
900   @NonNls public String SESSION_HI_PREFIX = "";        //SessionBean Home interface name prefix
901   /**
902  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
903  */
904   @NonNls public String SESSION_HI_SUFFIX = "Home";    //SessionBean Home interface name suffix
905   /**
906  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
907  */
908   @NonNls public String SESSION_RI_PREFIX = "";        //SessionBean Remote interface name prefix
909   /**
910  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
911  */
912   @NonNls public String SESSION_RI_SUFFIX = "";        //SessionBean Remote interface name prefix
913   /**
914  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
915  */
916   @NonNls public String SESSION_LHI_PREFIX = "Local";  //SessionBean local Home interface name prefix
917   /**
918  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
919  */
920   @NonNls public String SESSION_LHI_SUFFIX = "Home";   //SessionBean local Home interface name suffix
921   /**
922  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
923  */
924   @NonNls public String SESSION_LI_PREFIX = "Local";   //SessionBean local interface name prefix
925   /**
926  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
927  */
928   @NonNls public String SESSION_LI_SUFFIX = "";        //SessionBean local interface name suffix
929   /**
930  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
931  */
932   @NonNls public String SESSION_SI_PREFIX = "";   //SessionBean service endpoint interface name prefix
933   /**
934  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
935  */
936   @NonNls public String SESSION_SI_SUFFIX = "Service";        //SessionBean service endpoint interface name suffix
937   /**
938  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
939  */
940   @NonNls public String SESSION_DD_PREFIX = "";        //SessionBean deployment descriptor name prefix
941   /**
942  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
943  */
944   @NonNls public String SESSION_DD_SUFFIX = "EJB";     //SessionBean deployment descriptor name suffix
945
946   /**
947  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
948  */
949   @NonNls public String MESSAGE_EB_PREFIX = "";        //MessageBean EJB Class name prefix
950   /**
951  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
952  */
953   @NonNls public String MESSAGE_EB_SUFFIX = "Bean";    //MessageBean EJB Class name suffix
954   /**
955  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
956  */
957   @NonNls public String MESSAGE_DD_PREFIX = "";        //MessageBean deployment descriptor name prefix
958   /**
959  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
960  */
961   @NonNls public String MESSAGE_DD_SUFFIX = "EJB";     //MessageBean deployment descriptor name suffix
962 //----------------- Servlet NAMING CONVENTIONS -------------
963   /**
964  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
965  */
966   @NonNls public String SERVLET_CLASS_PREFIX = "";           //SERVLET Class name prefix
967   /**
968  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
969  */
970   @NonNls public String SERVLET_CLASS_SUFFIX = "";           //SERVLET Class name suffix
971   /**
972  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
973  */
974   @NonNls public String SERVLET_DD_PREFIX = "";              //SERVLET deployment descriptor name prefix
975   /**
976  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
977  */
978   @NonNls public String SERVLET_DD_SUFFIX = "";              //SERVLET deployment descriptor name suffix
979 //----------------- Web Filter NAMING CONVENTIONS -------------
980   /**
981  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
982  */
983   @NonNls public String FILTER_CLASS_PREFIX = "";          //Filter Class name prefix
984   /**
985  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
986  */
987   @NonNls public String FILTER_CLASS_SUFFIX = "";          //Filter Class name suffix
988   /**
989  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
990  */
991   @NonNls public String FILTER_DD_PREFIX = "";             //Filter deployment descriptor name prefix
992   /**
993  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
994  */
995   @NonNls public String FILTER_DD_SUFFIX = "";             //Filter deployment descriptor name suffix
996
997   /**
998  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
999  */
1000   @NonNls public String LISTENER_CLASS_PREFIX = "";          //Listener Class name prefix
1001   /**
1002  * @deprecated use com.intellij.javaee.JavaeeCodeStyleSettings class
1003  */
1004   @NonNls public String LISTENER_CLASS_SUFFIX = "";          //Listener Class name suffix
1005
1006 //------------------------------------------------------------------------
1007
1008   // ---------------------------------- Javadoc formatting options -------------------------
1009   public boolean ENABLE_JAVADOC_FORMATTING = true;
1010
1011   /**
1012    * Align parameter comments to longest parameter name
1013    */
1014   public boolean JD_ALIGN_PARAM_COMMENTS = true;
1015   public int JD_MIN_PARM_NAME_LENGTH = 0;
1016   public int JD_MAX_PARM_NAME_LENGTH = 30;
1017
1018   /**
1019    * Align exception comments to longest exception name
1020    */
1021   public boolean JD_ALIGN_EXCEPTION_COMMENTS = true;
1022   public int JD_MIN_EXCEPTION_NAME_LENGTH = 0;
1023   public int JD_MAX_EXCEPTION_NAME_LENGTH = 30;
1024
1025   public boolean JD_ADD_BLANK_AFTER_PARM_COMMENTS = false;
1026   public boolean JD_ADD_BLANK_AFTER_RETURN = false;
1027   public boolean JD_ADD_BLANK_AFTER_DESCRIPTION = true;
1028   public boolean JD_P_AT_EMPTY_LINES = true;
1029
1030   public boolean JD_KEEP_INVALID_TAGS = true;
1031   public boolean JD_KEEP_EMPTY_LINES = true;
1032   public boolean JD_DO_NOT_WRAP_ONE_LINE_COMMENTS = false;
1033
1034   public boolean JD_USE_THROWS_NOT_EXCEPTION = true;
1035   public boolean JD_KEEP_EMPTY_PARAMETER = true;
1036   public boolean JD_KEEP_EMPTY_EXCEPTION = true;
1037   public boolean JD_KEEP_EMPTY_RETURN = true;
1038
1039
1040   public boolean JD_LEADING_ASTERISKS_ARE_ENABLED = true;
1041
1042   // ---------------------------------------------------------------------------------------
1043
1044
1045   // ---------------------------------- XML formatting options -------------------------
1046   public boolean XML_KEEP_WHITESPACES = false;
1047   public int XML_ATTRIBUTE_WRAP = WRAP_AS_NEEDED;
1048   public int XML_TEXT_WRAP = WRAP_AS_NEEDED;
1049
1050   public boolean XML_KEEP_LINE_BREAKS = true;
1051   public boolean XML_KEEP_LINE_BREAKS_IN_TEXT = true;
1052   public int XML_KEEP_BLANK_LINES = 2;
1053
1054   public boolean XML_ALIGN_ATTRIBUTES = true;
1055   public boolean XML_ALIGN_TEXT = false;
1056
1057   public boolean XML_SPACE_AROUND_EQUALITY_IN_ATTRIBUTE = false;
1058   public boolean XML_SPACE_AFTER_TAG_NAME = false;
1059   public boolean XML_SPACE_INSIDE_EMPTY_TAG = false;
1060
1061   // ---------------------------------------------------------------------------------------
1062
1063   // ---------------------------------- HTML formatting options -------------------------
1064   public boolean HTML_KEEP_WHITESPACES = false;
1065   public int HTML_ATTRIBUTE_WRAP = WRAP_AS_NEEDED;
1066   public int HTML_TEXT_WRAP = WRAP_AS_NEEDED;
1067
1068   public boolean HTML_KEEP_LINE_BREAKS = true;
1069   public boolean HTML_KEEP_LINE_BREAKS_IN_TEXT = true;
1070   public int HTML_KEEP_BLANK_LINES = 2;
1071
1072   public boolean HTML_ALIGN_ATTRIBUTES = true;
1073   public boolean HTML_ALIGN_TEXT = false;
1074
1075   public boolean HTML_SPACE_AROUND_EQUALITY_IN_ATTRINUTE = false;
1076   public boolean HTML_SPACE_AFTER_TAG_NAME = false;
1077   public boolean HTML_SPACE_INSIDE_EMPTY_TAG = false;
1078
1079   @NonNls public String HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE = "body,div,p,form,h1,h2,h3";
1080   @NonNls public String HTML_ELEMENTS_TO_REMOVE_NEW_LINE_BEFORE = "br";
1081   @NonNls public String HTML_DO_NOT_INDENT_CHILDREN_OF = "html,body,thead,tbody,tfoot";
1082   public int HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES = 200;
1083
1084   @NonNls public String HTML_KEEP_WHITESPACES_INSIDE = "span,pre";
1085   @NonNls public String HTML_INLINE_ELEMENTS =
1086     "a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,span,strike,strong,sub,sup,textarea,tt,u,var";
1087   @NonNls public String HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT = "title,h1,h2,h3,h4,h5,h6,p";
1088
1089   // ---------------------------------------------------------------------------------------
1090
1091
1092   // true if <%page import="x.y.z, x.y.t"%>
1093   // false if <%page import="x.y.z"%>
1094   //          <%page import="x.y.t"%>
1095   public boolean JSP_PREFER_COMMA_SEPARATED_IMPORT_LIST = false;
1096
1097   //----------------------------------------------------------------------------------------
1098
1099   //-------------- Annotation formatting settings-------------------------------------------
1100
1101   public int METHOD_ANNOTATION_WRAP = WRAP_ALWAYS;
1102   public int CLASS_ANNOTATION_WRAP = WRAP_ALWAYS;
1103   public int FIELD_ANNOTATION_WRAP = WRAP_ALWAYS;
1104   public int PARAMETER_ANNOTATION_WRAP = DO_NOT_WRAP;
1105   public int VARIABLE_ANNOTATION_WRAP = DO_NOT_WRAP;
1106
1107   public boolean SPACE_BEFORE_ANOTATION_PARAMETER_LIST = false;
1108   public boolean SPACE_WITHIN_ANNOTATION_PARENTHESES = false;
1109
1110   //----------------------------------------------------------------------------------------
1111
1112
1113   //-------------------------Enums----------------------------------------------------------
1114   public int ENUM_CONSTANTS_WRAP = DO_NOT_WRAP;
1115   //----------------------------------------------------------------------------------------
1116
1117   private CodeStyleSettings myParentSettings;
1118   private boolean myLoadedAdditionalIndentOptions;
1119
1120   public void readExternal(Element element) throws InvalidDataException {
1121     DefaultJDOMExternalizer.readExternal(this, element);
1122     if (LAYOUT_STATIC_IMPORTS_SEPARATELY) {
1123       // add <all other static imports> entry if there is none
1124       boolean found = false;
1125       for (PackageEntry entry : IMPORT_LAYOUT_TABLE.getEntries()) {
1126         if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
1127           found = true;
1128           break;
1129         }
1130       }
1131       if (!found) {
1132         PackageEntry last = IMPORT_LAYOUT_TABLE.getEntryCount() == 0 ? null : IMPORT_LAYOUT_TABLE.getEntryAt(IMPORT_LAYOUT_TABLE.getEntryCount() - 1);
1133         if (last != PackageEntry.BLANK_LINE_ENTRY) {
1134           IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
1135         }
1136         IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
1137       }
1138     }
1139     importOldIndentOptions(element);
1140     for (final CustomCodeStyleSettings settings : myCustomSettings.values()) {
1141       settings.readExternal(element);
1142     }
1143
1144     final List list = element.getChildren(ADDITIONAL_INDENT_OPTIONS);
1145     if (list != null) {
1146       for(Object o:list) {
1147         if (o instanceof Element) {
1148           final Element additionalIndentElement = (Element)o;
1149           final String fileTypeId = additionalIndentElement.getAttributeValue(FILETYPE);
1150
1151           if (fileTypeId != null && fileTypeId.length() > 0) {
1152             FileType target = FileTypeManager.getInstance().getFileTypeByExtension(fileTypeId);
1153             if (FileTypes.UNKNOWN == target || FileTypes.PLAIN_TEXT == target) {
1154               target = new TempFileType(fileTypeId);
1155             }
1156
1157             final IndentOptions options = new IndentOptions();
1158             options.readExternal(additionalIndentElement);
1159             registerAdditionalIndentOptions(target, options);
1160           }
1161         }
1162       }
1163     }
1164
1165     copyOldIndentOptions("java", JAVA_INDENT_OPTIONS);
1166     copyOldIndentOptions("jsp", JSP_INDENT_OPTIONS);
1167     copyOldIndentOptions("xml", XML_INDENT_OPTIONS);
1168   }
1169
1170   private void copyOldIndentOptions(@NonNls final String extension, final IndentOptions options) {
1171     final FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(extension);
1172     if (fileType != FileTypes.UNKNOWN && fileType != FileTypes.PLAIN_TEXT && !myAdditionalIndentOptions.containsKey(fileType)) {
1173       registerAdditionalIndentOptions(fileType, options);
1174     }
1175   }
1176
1177   private void importOldIndentOptions(@NonNls Element element) {
1178     final List options = element.getChildren("option");
1179     for (Object option1 : options) {
1180       @NonNls Element option = (Element)option1;
1181       @NonNls final String name = option.getAttributeValue("name");
1182       if ("TAB_SIZE".equals(name)) {
1183         final int value = Integer.valueOf(option.getAttributeValue("value")).intValue();
1184         JAVA_INDENT_OPTIONS.TAB_SIZE = value;
1185         JSP_INDENT_OPTIONS.TAB_SIZE = value;
1186         XML_INDENT_OPTIONS.TAB_SIZE = value;
1187         OTHER_INDENT_OPTIONS.TAB_SIZE = value;
1188       }
1189       else if ("INDENT_SIZE".equals(name)) {
1190         final int value = Integer.valueOf(option.getAttributeValue("value")).intValue();
1191         JAVA_INDENT_OPTIONS.INDENT_SIZE = value;
1192         JSP_INDENT_OPTIONS.INDENT_SIZE = value;
1193         XML_INDENT_OPTIONS.INDENT_SIZE = value;
1194         OTHER_INDENT_OPTIONS.INDENT_SIZE = value;
1195       }
1196       else if ("CONTINUATION_INDENT_SIZE".equals(name)) {
1197         final int value = Integer.valueOf(option.getAttributeValue("value")).intValue();
1198         JAVA_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
1199         JSP_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
1200         XML_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
1201         OTHER_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
1202       }
1203       else if ("USE_TAB_CHARACTER".equals(name)) {
1204         final boolean value = Boolean.valueOf(option.getAttributeValue("value")).booleanValue();
1205         JAVA_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
1206         JSP_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
1207         XML_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
1208         OTHER_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
1209       }
1210       else if ("SMART_TABS".equals(name)) {
1211         final boolean value = Boolean.valueOf(option.getAttributeValue("value")).booleanValue();
1212         JAVA_INDENT_OPTIONS.SMART_TABS = value;
1213         JSP_INDENT_OPTIONS.SMART_TABS = value;
1214         XML_INDENT_OPTIONS.SMART_TABS = value;
1215         OTHER_INDENT_OPTIONS.SMART_TABS = value;
1216       }
1217     }
1218   }
1219
1220   public void writeExternal(Element element) throws WriteExternalException {
1221     final CodeStyleSettings parentSettings = new CodeStyleSettings();
1222     DefaultJDOMExternalizer.writeExternal(this, element, new DifferenceFilter<CodeStyleSettings>(this, parentSettings));
1223     List<CustomCodeStyleSettings> customSettings = new ArrayList<CustomCodeStyleSettings>(myCustomSettings.values());
1224     
1225     Collections.sort(customSettings, new Comparator<CustomCodeStyleSettings>(){
1226       public int compare(final CustomCodeStyleSettings o1, final CustomCodeStyleSettings o2) {
1227         return o1.getTagName().compareTo(o2.getTagName());
1228       }
1229     });
1230
1231     for (final CustomCodeStyleSettings settings : customSettings) {
1232       final CustomCodeStyleSettings parentCustomSettings = parentSettings.getCustomSettings(settings.getClass());
1233       assert parentCustomSettings != null;
1234       settings.writeExternal(element, parentCustomSettings);
1235     }
1236
1237     final FileType[] fileTypes = myAdditionalIndentOptions.keySet().toArray(new FileType[myAdditionalIndentOptions.keySet().size()]);
1238     Arrays.sort(fileTypes, new Comparator<FileType>() {
1239       public int compare(final FileType o1, final FileType o2) {
1240         return o1.getDefaultExtension().compareTo(o2.getDefaultExtension());
1241       }
1242     });
1243
1244     for (FileType fileType : fileTypes) {
1245       final IndentOptions indentOptions = myAdditionalIndentOptions.get(fileType);
1246       Element additionalIndentOptions = new Element(ADDITIONAL_INDENT_OPTIONS);
1247       indentOptions.writeExternal(additionalIndentOptions);
1248       additionalIndentOptions.setAttribute(FILETYPE,fileType.getDefaultExtension());
1249       element.addContent(additionalIndentOptions);
1250     }
1251   }
1252
1253   public IndentOptions getIndentOptions(FileType fileType) {
1254     if (USE_SAME_INDENTS || fileType == null) return OTHER_INDENT_OPTIONS;
1255
1256     if (!myLoadedAdditionalIndentOptions) {
1257       loadAdditionalIndentOptions();
1258     }
1259     final IndentOptions indentOptions = myAdditionalIndentOptions.get(fileType);
1260     if (indentOptions != null) return indentOptions;
1261
1262     return OTHER_INDENT_OPTIONS;
1263   }
1264
1265   public boolean isSmartTabs(FileType fileType) {
1266     return getIndentOptions(fileType).SMART_TABS;
1267   }
1268
1269   public int getIndentSize(FileType fileType) {
1270     return getIndentOptions(fileType).INDENT_SIZE;
1271   }
1272
1273   public int getContinuationIndentSize(FileType fileType) {
1274     return getIndentOptions(fileType).CONTINUATION_INDENT_SIZE;
1275   }
1276
1277   public int getLabelIndentSize(FileType fileType) {
1278     return getIndentOptions(fileType).LABEL_INDENT_SIZE;
1279   }
1280
1281   public boolean getLabelIndentAbsolute(FileType fileType) {
1282     return getIndentOptions(fileType).LABEL_INDENT_ABSOLUTE;
1283   }
1284
1285   public int getTabSize(FileType fileType) {
1286     return getIndentOptions(fileType).TAB_SIZE;
1287   }
1288
1289   public boolean useTabCharacter(FileType fileType) {
1290     return getIndentOptions(fileType).USE_TAB_CHARACTER;
1291   }
1292
1293   public static class TypeToNameMap implements JDOMExternalizable {
1294     private final List<String> myPatterns = new ArrayList<String>();
1295     private final List<String> myNames = new ArrayList<String>();
1296
1297     public void addPair(String pattern, String name) {
1298       myPatterns.add(pattern);
1299       myNames.add(name);
1300     }
1301
1302     public String nameByType(String type) {
1303       for (int i = 0; i < myPatterns.size(); i++) {
1304         String pattern = myPatterns.get(i);
1305         if (StringUtil.startsWithChar(pattern, '*')) {
1306           if (type.endsWith(pattern.substring(1))) {
1307             return myNames.get(i);
1308           }
1309         }
1310         else {
1311           if (type.equals(pattern)) {
1312             return myNames.get(i);
1313           }
1314         }
1315       }
1316       return null;
1317     }
1318
1319     public void readExternal(@NonNls Element element) throws InvalidDataException {
1320       myPatterns.clear();
1321       myNames.clear();
1322       for (final Object o : element.getChildren("pair")) {
1323         @NonNls Element e = (Element)o;
1324
1325         String pattern = e.getAttributeValue("type");
1326         String name = e.getAttributeValue("name");
1327         if (pattern == null || name == null) {
1328           throw new InvalidDataException();
1329         }
1330         myPatterns.add(pattern);
1331         myNames.add(name);
1332
1333       }
1334     }
1335
1336     public void writeExternal(Element parentNode) throws WriteExternalException {
1337       for (int i = 0; i < myPatterns.size(); i++) {
1338         String pattern = myPatterns.get(i);
1339         String name = myNames.get(i);
1340         @NonNls Element element = new Element("pair");
1341         parentNode.addContent(element);
1342         element.setAttribute("type", pattern);
1343         element.setAttribute("name", name);
1344       }
1345     }
1346
1347     public void copyFrom(TypeToNameMap from) {
1348       assert from != this;
1349       myPatterns.clear();
1350       myPatterns.addAll(from.myPatterns);
1351       myNames.clear();
1352       myNames.addAll(from.myNames);
1353     }
1354
1355     public boolean equals(Object other) {
1356       if (other instanceof TypeToNameMap) {
1357         TypeToNameMap otherMap = (TypeToNameMap)other;
1358         if (myPatterns.size() != otherMap.myPatterns.size()) {
1359           return false;
1360         }
1361         if (myNames.size() != otherMap.myNames.size()) {
1362           return false;
1363         }
1364         for (int i = 0; i < myPatterns.size(); i++) {
1365           String s1 = myPatterns.get(i);
1366           String s2 = otherMap.myPatterns.get(i);
1367           if (!Comparing.equal(s1, s2)) {
1368             return false;
1369           }
1370         }
1371         for (int i = 0; i < myNames.size(); i++) {
1372           String s1 = myNames.get(i);
1373           String s2 = otherMap.myNames.get(i);
1374           if (!Comparing.equal(s1, s2)) {
1375             return false;
1376           }
1377         }
1378         return true;
1379       }
1380       return false;
1381     }
1382
1383     public int hashCode() {
1384       int code = 0;
1385       for (String myPattern : myPatterns) {
1386         code += myPattern.hashCode();
1387       }
1388       for (String myName : myNames) {
1389         code += myName.hashCode();
1390       }
1391       return code;
1392     }
1393
1394   }
1395
1396   private void registerAdditionalIndentOptions(FileType fileType, IndentOptions options) {
1397     myAdditionalIndentOptions.put(fileType, options);
1398   }
1399
1400   public IndentOptions getAdditionalIndentOptions(FileType fileType) {
1401     if (!myLoadedAdditionalIndentOptions) {
1402       loadAdditionalIndentOptions();
1403     }
1404     return myAdditionalIndentOptions.get(fileType);
1405   }
1406
1407   private void loadAdditionalIndentOptions() {
1408     myLoadedAdditionalIndentOptions = true;
1409     final FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME);
1410     for (final FileTypeIndentOptionsProvider provider : providers) {
1411       if (!myAdditionalIndentOptions.containsKey(provider.getFileType())) {
1412         registerAdditionalIndentOptions(provider.getFileType(), provider.createIndentOptions());
1413       }
1414     }
1415   }
1416
1417   @TestOnly
1418   public void clearCodeStyleSettings() throws Exception {
1419     CodeStyleSettings cleanSettings = new CodeStyleSettings();
1420     copyFrom(cleanSettings);
1421     myAdditionalIndentOptions.clear(); //hack
1422     myLoadedAdditionalIndentOptions = false;
1423   }
1424
1425   private static class TempFileType implements FileType {
1426     private final String myExtension;
1427
1428     private TempFileType(@NotNull final String extension) {
1429       myExtension = extension;
1430     }
1431
1432     @NotNull
1433     public String getName() {
1434       return "TempFileType";
1435     }
1436
1437     @NotNull
1438     public String getDescription() {
1439       return "TempFileType";
1440     }
1441
1442     @NotNull
1443     public String getDefaultExtension() {
1444       return myExtension;
1445     }
1446
1447     public Icon getIcon() {
1448       return null;
1449     }
1450
1451     public boolean isBinary() {
1452       return false;
1453     }
1454
1455     public boolean isReadOnly() {
1456       return false;
1457     }
1458
1459     public String getCharset(@NotNull VirtualFile file, byte[] content) {
1460       return null;
1461     }
1462   }
1463 }