1 11 package org.eclipse.jdt.internal.formatter; 12 13 import java.util.HashMap ; 14 import java.util.Map ; 15 16 import org.eclipse.jdt.core.JavaCore; 17 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 18 import org.eclipse.jdt.core.compiler.InvalidInputException; 19 import org.eclipse.jdt.core.formatter.CodeFormatter; 20 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; 21 import org.eclipse.jdt.internal.compiler.ast.ASTNode; 22 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; 23 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; 24 import org.eclipse.jdt.internal.compiler.ast.Expression; 25 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 26 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 27 import org.eclipse.jdt.internal.compiler.parser.Scanner; 28 import org.eclipse.jdt.internal.compiler.util.Util; 29 import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil; 30 import org.eclipse.jdt.internal.formatter.comment.CommentRegion; 31 import org.eclipse.jdt.internal.formatter.comment.JavaDocRegion; 32 import org.eclipse.jdt.internal.formatter.comment.MultiCommentRegion; 33 import org.eclipse.jface.text.Document; 34 import org.eclipse.jface.text.IDocument; 35 import org.eclipse.jface.text.Position; 36 import org.eclipse.text.edits.MultiTextEdit; 37 import org.eclipse.text.edits.TextEdit; 38 39 public class DefaultCodeFormatter extends CodeFormatter { 40 41 public static final boolean DEBUG = false; 42 private static Scanner ProbingScanner; 43 44 54 public static CommentRegion createRegion(int kind, IDocument document, Position range, CodeFormatterVisitor formatter) { 55 switch (kind) { 56 case CodeFormatter.K_SINGLE_LINE_COMMENT: 57 return new CommentRegion(document, range, formatter); 58 case CodeFormatter.K_MULTI_LINE_COMMENT: 59 return new MultiCommentRegion(document, range, formatter); 60 case CodeFormatter.K_JAVA_DOC: 61 return new JavaDocRegion(document, range, formatter); 62 } 63 return null; 64 } 65 66 private CodeSnippetParsingUtil codeSnippetParsingUtil; 67 private Map defaultCompilerOptions; 68 69 private CodeFormatterVisitor newCodeFormatter; 70 private Map options; 71 72 private DefaultCodeFormatterOptions preferences; 73 74 public DefaultCodeFormatter() { 75 this(new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getJavaConventionsSettings()), null); 76 } 77 78 public DefaultCodeFormatter(DefaultCodeFormatterOptions preferences) { 79 this(preferences, null); 80 } 81 82 public DefaultCodeFormatter(DefaultCodeFormatterOptions defaultCodeFormatterOptions, Map options) { 83 if (options != null) { 84 this.options = options; 85 this.preferences = new DefaultCodeFormatterOptions(options); 86 } else { 87 this.options = JavaCore.getOptions(); 88 this.preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getJavaConventionsSettings()); 89 } 90 this.defaultCompilerOptions = getDefaultCompilerOptions(); 91 if (defaultCodeFormatterOptions != null) { 92 this.preferences.set(defaultCodeFormatterOptions.getMap()); 93 } 94 } 95 96 public DefaultCodeFormatter(Map options) { 97 this(null, options); 98 } 99 100 public String createIndentationString(final int indentationLevel) { 101 if (indentationLevel < 0) { 102 throw new IllegalArgumentException (); 103 } 104 105 int tabs = 0; 106 int spaces = 0; 107 switch(this.preferences.tab_char) { 108 case DefaultCodeFormatterOptions.SPACE : 109 spaces = indentationLevel * this.preferences.tab_size; 110 break; 111 case DefaultCodeFormatterOptions.TAB : 112 tabs = indentationLevel; 113 break; 114 case DefaultCodeFormatterOptions.MIXED : 115 int tabSize = this.preferences.tab_size; 116 int spaceEquivalents = indentationLevel * this.preferences.indentation_size; 117 tabs = spaceEquivalents / tabSize; 118 spaces = spaceEquivalents % tabSize; 119 break; 120 default: 121 return Util.EMPTY_STRING; 122 } 123 if (tabs == 0 && spaces == 0) { 124 return Util.EMPTY_STRING; 125 } 126 StringBuffer buffer = new StringBuffer (tabs + spaces); 127 for(int i = 0; i < tabs; i++) { 128 buffer.append('\t'); 129 } 130 for(int i = 0; i < spaces; i++) { 131 buffer.append(' '); 132 } 133 return buffer.toString(); 134 } 135 136 139 public TextEdit format( 140 int kind, 141 String source, 142 int offset, 143 int length, 144 int indentationLevel, 145 String lineSeparator) { 146 147 if (offset < 0 || length < 0 || length > source.length()) { 148 throw new IllegalArgumentException (); 149 } 150 this.codeSnippetParsingUtil = new CodeSnippetParsingUtil(); 151 switch(kind) { 152 case K_CLASS_BODY_DECLARATIONS : 153 return formatClassBodyDeclarations(source, indentationLevel, lineSeparator, offset, length); 154 case K_COMPILATION_UNIT : 155 return formatCompilationUnit(source, indentationLevel, lineSeparator, offset, length); 156 case K_EXPRESSION : 157 return formatExpression(source, indentationLevel, lineSeparator, offset, length); 158 case K_STATEMENTS : 159 return formatStatements(source, indentationLevel, lineSeparator, offset, length); 160 case K_UNKNOWN : 161 return probeFormatting(source, indentationLevel, lineSeparator, offset, length); 162 case K_JAVA_DOC : 163 case K_MULTI_LINE_COMMENT : 164 case K_SINGLE_LINE_COMMENT : 165 return formatComment(kind, source, indentationLevel, lineSeparator, offset, length); 166 } 167 return null; 168 } 169 170 private TextEdit formatClassBodyDeclarations(String source, int indentationLevel, String lineSeparator, int offset, int length) { 171 ASTNode[] bodyDeclarations = this.codeSnippetParsingUtil.parseClassBodyDeclarations(source.toCharArray(), getDefaultCompilerOptions(), true); 172 173 if (bodyDeclarations == null) { 174 return null; 176 } 177 return internalFormatClassBodyDeclarations(source, indentationLevel, lineSeparator, bodyDeclarations, offset, length); 178 } 179 180 192 private TextEdit formatComment(int kind, String source, int indentationLevel, String lineSeparator, int offset, int length) { 193 Object oldOption = this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT); 194 boolean isFormattingComments = false; 195 if (oldOption == null) { 196 switch (kind) { 197 case CodeFormatter.K_SINGLE_LINE_COMMENT: 198 isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT)); 199 break; 200 case CodeFormatter.K_MULTI_LINE_COMMENT: 201 isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT)); 202 break; 203 case CodeFormatter.K_JAVA_DOC: 204 isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT)); 205 } 206 } else { 207 isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(oldOption); 208 } 209 if (isFormattingComments) { 210 if (lineSeparator != null) { 211 this.preferences.line_separator = lineSeparator; 212 } else { 213 this.preferences.line_separator = Util.LINE_SEPARATOR; 214 } 215 this.preferences.initial_indentation_level = indentationLevel; 216 this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, this.options, offset, length, null); 217 final CommentRegion region = createRegion(kind, new Document(source), new Position(offset, length), this.newCodeFormatter); 218 if (region != null) { 219 return this.newCodeFormatter.format(source, region); 220 } 221 } 222 return new MultiTextEdit(); 223 } 224 225 private TextEdit formatCompilationUnit(String source, int indentationLevel, String lineSeparator, int offset, int length) { 226 CompilationUnitDeclaration compilationUnitDeclaration = this.codeSnippetParsingUtil.parseCompilationUnit(source.toCharArray(), getDefaultCompilerOptions(), true); 227 228 if (lineSeparator != null) { 229 this.preferences.line_separator = lineSeparator; 230 } else { 231 this.preferences.line_separator = Util.LINE_SEPARATOR; 232 } 233 this.preferences.initial_indentation_level = indentationLevel; 234 235 this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, this.options, offset, length, this.codeSnippetParsingUtil); 236 237 return this.newCodeFormatter.format(source, compilationUnitDeclaration); 238 } 239 240 private TextEdit formatExpression(String source, int indentationLevel, String lineSeparator, int offset, int length) { 241 Expression expression = this.codeSnippetParsingUtil.parseExpression(source.toCharArray(), getDefaultCompilerOptions(), true); 242 243 if (expression == null) { 244 return null; 246 } 247 return internalFormatExpression(source, indentationLevel, lineSeparator, expression, offset, length); 248 } 249 250 private TextEdit formatStatements(String source, int indentationLevel, String lineSeparator, int offset, int length) { 251 ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false); 252 253 if (constructorDeclaration.statements == null) { 254 return null; 256 } 257 return internalFormatStatements(source, indentationLevel, lineSeparator, constructorDeclaration, offset, length); 258 } 259 260 public String getDebugOutput() { 261 return this.newCodeFormatter.scribe.toString(); 262 } 263 264 private Map getDefaultCompilerOptions() { 265 if (this.defaultCompilerOptions == null) { 266 Map optionsMap = new HashMap (30); 267 optionsMap.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE); 268 optionsMap.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.DO_NOT_GENERATE); 269 optionsMap.put(CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.DO_NOT_GENERATE); 270 optionsMap.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.PRESERVE); 271 optionsMap.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.DISABLED); 272 optionsMap.put(CompilerOptions.OPTION_ReportMethodWithConstructorName, CompilerOptions.IGNORE); 273 optionsMap.put(CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod, CompilerOptions.IGNORE); 274 optionsMap.put(CompilerOptions.OPTION_ReportOverridingMethodWithoutSuperInvocation, CompilerOptions.IGNORE); 275 optionsMap.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE); 276 optionsMap.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.DISABLED); 277 optionsMap.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.DISABLED); 278 optionsMap.put(CompilerOptions.OPTION_ReportHiddenCatchBlock, CompilerOptions.IGNORE); 279 optionsMap.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE); 280 optionsMap.put(CompilerOptions.OPTION_ReportUnusedParameter, CompilerOptions.IGNORE); 281 optionsMap.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.IGNORE); 282 optionsMap.put(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, CompilerOptions.IGNORE); 283 optionsMap.put(CompilerOptions.OPTION_ReportNoEffectAssignment, CompilerOptions.IGNORE); 284 optionsMap.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.IGNORE); 285 optionsMap.put(CompilerOptions.OPTION_ReportNoImplicitStringConversion, CompilerOptions.IGNORE); 286 optionsMap.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE); 287 optionsMap.put(CompilerOptions.OPTION_ReportIndirectStaticAccess, CompilerOptions.IGNORE); 288 optionsMap.put(CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod, CompilerOptions.IGNORE); 289 optionsMap.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE); 290 optionsMap.put(CompilerOptions.OPTION_ReportLocalVariableHiding, CompilerOptions.IGNORE); 291 optionsMap.put(CompilerOptions.OPTION_ReportFieldHiding, CompilerOptions.IGNORE); 292 optionsMap.put(CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment, CompilerOptions.IGNORE); 293 optionsMap.put(CompilerOptions.OPTION_ReportEmptyStatement, CompilerOptions.IGNORE); 294 optionsMap.put(CompilerOptions.OPTION_ReportAssertIdentifier, CompilerOptions.IGNORE); 295 optionsMap.put(CompilerOptions.OPTION_ReportEnumIdentifier, CompilerOptions.IGNORE); 296 optionsMap.put(CompilerOptions.OPTION_ReportUndocumentedEmptyBlock, CompilerOptions.IGNORE); 297 optionsMap.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.IGNORE); 298 optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadoc, CompilerOptions.IGNORE); 299 optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, CompilerOptions.PUBLIC); 300 optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTags, CompilerOptions.DISABLED); 301 optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef, CompilerOptions.DISABLED); 302 optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef, CompilerOptions.DISABLED); 303 optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTags, CompilerOptions.IGNORE); 304 optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility, CompilerOptions.PUBLIC); 305 optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding, CompilerOptions.DISABLED); 306 optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocComments, CompilerOptions.IGNORE); 307 optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility, CompilerOptions.IGNORE); 308 optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding, CompilerOptions.DISABLED); 309 optionsMap.put(CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally, CompilerOptions.IGNORE); 310 optionsMap.put(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, CompilerOptions.IGNORE); 311 optionsMap.put(CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, CompilerOptions.DISABLED); 312 optionsMap.put(CompilerOptions.OPTION_ReportUnqualifiedFieldAccess, CompilerOptions.IGNORE); 313 optionsMap.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4); 314 optionsMap.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2); 315 optionsMap.put(CompilerOptions.OPTION_TaskTags, ""); optionsMap.put(CompilerOptions.OPTION_TaskPriorities, ""); optionsMap.put(CompilerOptions.OPTION_TaskCaseSensitive, CompilerOptions.DISABLED); 318 optionsMap.put(CompilerOptions.OPTION_ReportUnusedParameterWhenImplementingAbstract, CompilerOptions.DISABLED); 319 optionsMap.put(CompilerOptions.OPTION_ReportUnusedParameterWhenOverridingConcrete, CompilerOptions.DISABLED); 320 optionsMap.put(CompilerOptions.OPTION_ReportSpecialParameterHidingField, CompilerOptions.DISABLED); 321 optionsMap.put(CompilerOptions.OPTION_MaxProblemPerUnit, String.valueOf(100)); 322 optionsMap.put(CompilerOptions.OPTION_InlineJsr, CompilerOptions.DISABLED); 323 this.defaultCompilerOptions = optionsMap; 324 } 325 Object sourceOption = this.options.get(CompilerOptions.OPTION_Source); 326 if (sourceOption != null) { 327 this.defaultCompilerOptions.put(CompilerOptions.OPTION_Source, sourceOption); 328 } else { 329 this.defaultCompilerOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3); 330 } 331 return this.defaultCompilerOptions; 332 } 333 334 private TextEdit internalFormatClassBodyDeclarations(String source, int indentationLevel, String lineSeparator, ASTNode[] bodyDeclarations, int offset, int length) { 335 if (lineSeparator != null) { 336 this.preferences.line_separator = lineSeparator; 337 } else { 338 this.preferences.line_separator = Util.LINE_SEPARATOR; 339 } 340 this.preferences.initial_indentation_level = indentationLevel; 341 342 this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, this.options, offset, length, this.codeSnippetParsingUtil); 343 return this.newCodeFormatter.format(source, bodyDeclarations); 344 } 345 346 private TextEdit internalFormatExpression(String source, int indentationLevel, String lineSeparator, Expression expression, int offset, int length) { 347 if (lineSeparator != null) { 348 this.preferences.line_separator = lineSeparator; 349 } else { 350 this.preferences.line_separator = Util.LINE_SEPARATOR; 351 } 352 this.preferences.initial_indentation_level = indentationLevel; 353 354 this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, this.options, offset, length, this.codeSnippetParsingUtil); 355 356 TextEdit textEdit = this.newCodeFormatter.format(source, expression); 357 return textEdit; 358 } 359 360 private TextEdit internalFormatStatements(String source, int indentationLevel, String lineSeparator, ConstructorDeclaration constructorDeclaration, int offset, int length) { 361 if (lineSeparator != null) { 362 this.preferences.line_separator = lineSeparator; 363 } else { 364 this.preferences.line_separator = Util.LINE_SEPARATOR; 365 } 366 this.preferences.initial_indentation_level = indentationLevel; 367 368 this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, this.options, offset, length, this.codeSnippetParsingUtil); 369 370 return this.newCodeFormatter.format(source, constructorDeclaration); 371 } 372 373 private TextEdit probeFormatting(String source, int indentationLevel, String lineSeparator, int offset, int length) { 374 if (ProbingScanner == null) { 375 ProbingScanner = new Scanner(true, true, false, ClassFileConstants.JDK1_3, ClassFileConstants.JDK1_3, null, null, true); 377 } 378 ProbingScanner.setSource(source.toCharArray()); 379 ProbingScanner.resetTo(offset, offset + length); 380 try { 381 switch(ProbingScanner.getNextToken()) { 382 case ITerminalSymbols.TokenNameCOMMENT_BLOCK : 383 if (ProbingScanner.getCurrentTokenEndPosition() == offset + length - 1) { 384 return formatComment(K_MULTI_LINE_COMMENT, source, indentationLevel, lineSeparator, offset, length); 385 } 386 break; 387 case ITerminalSymbols.TokenNameCOMMENT_LINE : 388 if (ProbingScanner.getCurrentTokenEndPosition() == offset + length - 1) { 389 return formatComment(K_SINGLE_LINE_COMMENT, source, indentationLevel, lineSeparator, offset, length); 390 } 391 break; 392 case ITerminalSymbols.TokenNameCOMMENT_JAVADOC : 393 if (ProbingScanner.getCurrentTokenEndPosition() == offset + length - 1) { 394 return formatComment(K_JAVA_DOC, source, indentationLevel, lineSeparator, offset, length); 395 } 396 } 397 } catch (InvalidInputException e) { 398 } 400 ProbingScanner.setSource((char[]) null); 401 402 Expression expression = this.codeSnippetParsingUtil.parseExpression(source.toCharArray(), getDefaultCompilerOptions(), true); 404 if (expression != null) { 405 return internalFormatExpression(source, indentationLevel, lineSeparator, expression, offset, length); 406 } 407 408 ASTNode[] bodyDeclarations = this.codeSnippetParsingUtil.parseClassBodyDeclarations(source.toCharArray(), getDefaultCompilerOptions(), true); 410 if (bodyDeclarations != null) { 411 return internalFormatClassBodyDeclarations(source, indentationLevel, lineSeparator, bodyDeclarations, offset, length); 412 } 413 414 ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false); 416 if (constructorDeclaration.statements != null) { 417 return internalFormatStatements(source, indentationLevel, lineSeparator, constructorDeclaration, offset, length); 418 } 419 420 return formatCompilationUnit(source, indentationLevel, lineSeparator, offset, length); 422 } 423 } 424 | Popular Tags |