1 11 package org.eclipse.jdt.internal.corext.template.java; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import java.util.ArrayList ; 15 import java.util.Arrays ; 16 import java.util.Comparator ; 17 import java.util.HashMap ; 18 import java.util.HashSet ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IProgressMonitor; 24 import org.eclipse.core.runtime.IStatus; 25 import org.eclipse.core.runtime.NullProgressMonitor; 26 import org.eclipse.core.runtime.Status; 27 28 import org.eclipse.swt.widgets.Shell; 29 30 import org.eclipse.jface.dialogs.MessageDialog; 31 import org.eclipse.jface.preference.IPreferenceStore; 32 33 import org.eclipse.jface.text.BadLocationException; 34 import org.eclipse.jface.text.BadPositionCategoryException; 35 import org.eclipse.jface.text.DefaultPositionUpdater; 36 import org.eclipse.jface.text.Document; 37 import org.eclipse.jface.text.IDocument; 38 import org.eclipse.jface.text.IPositionUpdater; 39 import org.eclipse.jface.text.IRegion; 40 import org.eclipse.jface.text.Position; 41 import org.eclipse.jface.text.TextUtilities; 42 import org.eclipse.jface.text.templates.Template; 43 import org.eclipse.jface.text.templates.TemplateBuffer; 44 import org.eclipse.jface.text.templates.TemplateContextType; 45 import org.eclipse.jface.text.templates.TemplateException; 46 import org.eclipse.jface.text.templates.TemplateTranslator; 47 import org.eclipse.jface.text.templates.TemplateVariable; 48 import org.eclipse.jface.text.templates.TemplateVariableType; 49 50 import org.eclipse.jdt.core.Flags; 51 import org.eclipse.jdt.core.ICompilationUnit; 52 import org.eclipse.jdt.core.IJavaElement; 53 import org.eclipse.jdt.core.IJavaProject; 54 import org.eclipse.jdt.core.JavaModelException; 55 import org.eclipse.jdt.core.Signature; 56 import org.eclipse.jdt.core.dom.CompilationUnit; 57 import org.eclipse.jdt.core.dom.SimpleName; 58 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; 59 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; 60 import org.eclipse.jdt.core.search.IJavaSearchConstants; 61 import org.eclipse.jdt.core.search.IJavaSearchScope; 62 import org.eclipse.jdt.core.search.SearchEngine; 63 import org.eclipse.jdt.core.search.SearchPattern; 64 import org.eclipse.jdt.core.search.TypeNameMatch; 65 66 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; 67 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 68 import org.eclipse.jdt.internal.corext.template.java.CompilationUnitCompletion.Variable; 69 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 70 import org.eclipse.jdt.internal.corext.util.Strings; 71 import org.eclipse.jdt.internal.corext.util.TypeNameMatchCollector; 72 73 import org.eclipse.jdt.ui.JavaUI; 74 import org.eclipse.jdt.ui.PreferenceConstants; 75 76 import org.eclipse.jdt.internal.ui.JavaPlugin; 77 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; 78 import org.eclipse.jdt.internal.ui.text.correction.ASTResolving; 79 import org.eclipse.jdt.internal.ui.text.correction.SimilarElementsRequestor; 80 import org.eclipse.jdt.internal.ui.text.template.contentassist.MultiVariable; 81 import org.eclipse.jdt.internal.ui.text.template.contentassist.MultiVariableGuess; 82 import org.eclipse.jdt.internal.ui.util.ExceptionHandler; 83 84 87 public class JavaContext extends CompilationUnitContext { 88 89 90 private CompilationUnitCompletion fCompletion; 91 95 private Set fUsedNames= new HashSet (); 96 private Map fVariables= new HashMap (); 97 98 107 public JavaContext(TemplateContextType type, IDocument document, int completionOffset, int completionLength, ICompilationUnit compilationUnit) { 108 super(type, document, completionOffset, completionLength, compilationUnit); 109 } 110 111 120 public JavaContext(TemplateContextType type, IDocument document, Position completionPosition, ICompilationUnit compilationUnit) { 121 super(type, document, completionPosition, compilationUnit); 122 } 123 124 129 private int getIndentation() { 130 int start= getStart(); 131 IDocument document= getDocument(); 132 try { 133 IRegion region= document.getLineInformationOfOffset(start); 134 String lineContent= document.get(region.getOffset(), region.getLength()); 135 IJavaProject project= getJavaProject(); 136 return Strings.computeIndentUnits(lineContent, project); 137 } catch (BadLocationException e) { 138 return 0; 139 } 140 } 141 142 145 public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException { 146 clear(); 147 148 if (!canEvaluate(template)) 149 throw new TemplateException(JavaTemplateMessages.Context_error_cannot_evaluate); 150 151 TemplateTranslator translator= new TemplateTranslator() { 152 protected TemplateVariable createVariable(TemplateVariableType type, String name, int[] offsets) { 153 156 MultiVariable variable= new JavaVariable(type, name, offsets); 157 fVariables.put(name, variable); 158 return variable; 159 } 160 }; 161 TemplateBuffer buffer= translator.translate(template); 162 163 getContextType().resolve(buffer, this); 164 165 IPreferenceStore prefs= JavaPlugin.getDefault().getPreferenceStore(); 166 boolean useCodeFormatter= prefs.getBoolean(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER); 167 168 IJavaProject project= getJavaProject(); 169 JavaFormatter formatter= new JavaFormatter(TextUtilities.getDefaultLineDelimiter(getDocument()), getIndentation(), useCodeFormatter, project); 170 formatter.format(buffer, this); 171 172 clear(); 173 174 return buffer; 175 } 176 177 private void clear() { 178 fUsedNames.clear(); 179 } 180 181 184 public boolean canEvaluate(Template template) { 185 if (fForceEvaluation) 186 return true; 187 188 String key= getKey(); 189 return 190 template.matches(key, getContextType().getId()) && 191 key.length() != 0 && template.getName().toLowerCase().startsWith(key.toLowerCase()); 192 } 193 194 197 public int getStart() { 198 199 if (fIsManaged && getCompletionLength() > 0) 200 return super.getStart(); 201 202 try { 203 IDocument document= getDocument(); 204 205 int start= getCompletionOffset(); 206 int end= getCompletionOffset() + getCompletionLength(); 207 208 while (start != 0 && Character.isUnicodeIdentifierPart(document.getChar(start - 1))) 209 start--; 210 211 while (start != end && Character.isWhitespace(document.getChar(start))) 212 start++; 213 214 if (start == end) 215 start= getCompletionOffset(); 216 217 return start; 218 219 } catch (BadLocationException e) { 220 return super.getStart(); 221 } 222 } 223 224 227 public int getEnd() { 228 229 if (fIsManaged || getCompletionLength() == 0) 230 return super.getEnd(); 231 232 try { 233 IDocument document= getDocument(); 234 235 int start= getCompletionOffset(); 236 int end= getCompletionOffset() + getCompletionLength(); 237 238 while (start != end && Character.isWhitespace(document.getChar(end - 1))) 239 end--; 240 241 return end; 242 243 } catch (BadLocationException e) { 244 return super.getEnd(); 245 } 246 } 247 248 251 public String getKey() { 252 253 if (getCompletionLength() == 0) 254 return super.getKey(); 255 256 try { 257 IDocument document= getDocument(); 258 259 int start= getStart(); 260 int end= getCompletionOffset(); 261 return start <= end 262 ? document.get(start, end - start) 263 : ""; 265 } catch (BadLocationException e) { 266 return super.getKey(); 267 } 268 } 269 270 275 public char getCharacterBeforeStart() { 276 int start= getStart(); 277 278 try { 279 return start == 0 280 ? ' ' 281 : getDocument().getChar(start - 1); 282 283 } catch (BadLocationException e) { 284 return ' '; 285 } 286 } 287 288 private static void handleException(Shell shell, Exception e) { 289 String title= JavaTemplateMessages.JavaContext_error_title; 290 if (e instanceof CoreException) 291 ExceptionHandler.handle((CoreException)e, shell, title, null); 292 else if (e instanceof InvocationTargetException ) 293 ExceptionHandler.handle((InvocationTargetException )e, shell, title, null); 294 else { 295 JavaPlugin.log(e); 296 MessageDialog.openError(shell, title, e.getMessage()); 297 } 298 } 299 300 private CompilationUnitCompletion getCompletion() { 301 ICompilationUnit compilationUnit= getCompilationUnit(); 302 if (fCompletion == null) { 303 fCompletion= new CompilationUnitCompletion(compilationUnit); 304 305 if (compilationUnit != null) { 306 try { 307 compilationUnit.codeComplete(getStart(), fCompletion); 308 } catch (JavaModelException e) { 309 } 311 } 312 } 313 314 return fCompletion; 315 } 316 317 322 public Variable[] getArrays() { 323 Variable[] localArrays= getCompletion().findLocalArrays(); 324 arrange(localArrays); 325 return localArrays; 326 } 327 328 334 private void arrange(Variable[] variables) { 335 Arrays.sort(variables, new Comparator () { 336 public int compare(Object o1, Object o2) { 337 return rank((Variable) o1) - rank((Variable) o2); 338 } 339 340 private int rank(Variable l) { 341 return fUsedNames.contains(l.getName()) ? 1 : 0; 342 } 343 }); 344 } 345 346 352 public Variable[] getLocalVariables(String type) { 353 Variable[] localVariables= getCompletion().findLocalVariables(type); 354 arrange(localVariables); 355 return localVariables; 356 } 357 358 364 public Variable[] getFields(String type) { 365 Variable[] fields= getCompletion().findFieldVariables(type); 366 arrange(fields); 367 return fields; 368 } 369 370 375 public Variable[] getIterables() { 376 Variable[] iterables= getCompletion().findLocalIterables(); 377 arrange(iterables); 378 return iterables; 379 } 380 381 public void markAsUsed(String name) { 382 fUsedNames.add(name); 383 } 384 385 public String [] suggestVariableNames(String type) throws IllegalArgumentException { 386 String [] excludes= computeExcludes(); 387 String [] result= suggestVariableName(type, excludes); 389 return result; 390 } 391 392 private String [] computeExcludes() { 393 String [] excludes= getCompletion().getLocalVariableNames(); 394 if (!fUsedNames.isEmpty()) { 395 String [] allExcludes= new String [fUsedNames.size() + excludes.length]; 396 System.arraycopy(excludes, 0, allExcludes, 0, excludes.length); 397 System.arraycopy(fUsedNames.toArray(), 0, allExcludes, 0, fUsedNames.size()); 398 excludes= allExcludes; 399 } 400 return excludes; 401 } 402 403 private String [] suggestVariableName(String type, String [] excludes) throws IllegalArgumentException { 404 int dim=0; 405 while (type.endsWith("[]")) { dim++; 407 type= type.substring(0, type.length() - 2); 408 } 409 410 IJavaProject project= getJavaProject(); 411 if (project != null) 412 return StubUtility.getVariableNameSuggestions(StubUtility.LOCAL, project, type, dim, Arrays.asList(excludes), true); 413 414 return new String [] {Signature.getSimpleName(type).toLowerCase()}; 416 } 417 418 public void addImport(String type) { 419 if (isReadOnly()) 420 return; 421 422 ICompilationUnit cu= getCompilationUnit(); 423 if (cu == null) 424 return; 425 426 try { 427 boolean qualified= type.indexOf('.') != -1; 428 if (!qualified) { 429 IJavaSearchScope searchScope= SearchEngine.createJavaSearchScope(new IJavaElement[] { cu.getJavaProject() }); 430 SimpleName nameNode= null; 431 TypeNameMatch[] matches= findAllTypes(type, searchScope, nameNode, null, cu); 432 if (matches.length != 1) return; 434 type= matches[0].getFullyQualifiedName(); 435 } 436 437 Position position= new Position(getCompletionOffset(), getCompletionLength()); 438 IDocument document= getDocument(); 439 final String category= "__template_position_importer" + System.currentTimeMillis(); IPositionUpdater updater= new DefaultPositionUpdater(category); 441 document.addPositionCategory(category); 442 document.addPositionUpdater(updater); 443 document.addPosition(position); 444 445 try { 446 447 ImportRewrite rewrite= StubUtility.createImportRewrite(cu, true); 448 CompilationUnit root= getASTRoot(cu); 449 ImportRewriteContext context; 450 if (root == null) 451 context= null; 452 else 453 context= new ContextSensitiveImportRewriteContext(root, getCompletionOffset(), rewrite); 454 rewrite.addImport(type, context); 455 JavaModelUtil.applyEdit(cu, rewrite.rewriteImports(null), false, null); 456 457 setCompletionOffset(position.getOffset()); 458 setCompletionLength(position.getLength()); 459 460 } catch (CoreException e) { 461 handleException(null, e); 462 } finally { 463 document.removePosition(position); 464 document.removePositionUpdater(updater); 465 document.removePositionCategory(category); 466 } 467 468 } catch (BadLocationException e) { 469 handleException(null, e); 470 } catch (BadPositionCategoryException e) { 471 handleException(null, e); 472 } catch (JavaModelException e) { 473 handleException(null, e); 474 } 475 } 476 477 private CompilationUnit getASTRoot(ICompilationUnit compilationUnit) { 478 return JavaPlugin.getDefault().getASTProvider().getAST(compilationUnit, ASTProvider.WAIT_NO, new NullProgressMonitor()); 479 } 480 481 484 private TypeNameMatch[] findAllTypes(String simpleTypeName, IJavaSearchScope searchScope, SimpleName nameNode, IProgressMonitor monitor, ICompilationUnit cu) throws JavaModelException { 485 boolean is50OrHigher= JavaModelUtil.is50OrHigher(cu.getJavaProject()); 486 487 int typeKinds= SimilarElementsRequestor.ALL_TYPES; 488 if (nameNode != null) { 489 typeKinds= ASTResolving.getPossibleTypeKinds(nameNode, is50OrHigher); 490 } 491 492 ArrayList typeInfos= new ArrayList (); 493 TypeNameMatchCollector requestor= new TypeNameMatchCollector(typeInfos); 494 new SearchEngine().searchAllTypeNames(null, 0, simpleTypeName.toCharArray(), SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE, getSearchForConstant(typeKinds), searchScope, requestor, IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH, monitor); 495 496 ArrayList typeRefsFound= new ArrayList (typeInfos.size()); 497 for (int i= 0, len= typeInfos.size(); i < len; i++) { 498 TypeNameMatch curr= (TypeNameMatch) typeInfos.get(i); 499 if (curr.getPackageName().length() > 0) { if (isOfKind(curr, typeKinds, is50OrHigher) && isVisible(curr, cu)) { 501 typeRefsFound.add(curr); 502 } 503 } 504 } 505 return (TypeNameMatch[]) typeRefsFound.toArray(new TypeNameMatch[typeRefsFound.size()]); 506 } 507 508 private int getSearchForConstant(int typeKinds) { 509 final int CLASSES= SimilarElementsRequestor.CLASSES; 510 final int INTERFACES= SimilarElementsRequestor.INTERFACES; 511 final int ENUMS= SimilarElementsRequestor.ENUMS; 512 final int ANNOTATIONS= SimilarElementsRequestor.ANNOTATIONS; 513 514 switch (typeKinds & (CLASSES | INTERFACES | ENUMS | ANNOTATIONS)) { 515 case CLASSES: return IJavaSearchConstants.CLASS; 516 case INTERFACES: return IJavaSearchConstants.INTERFACE; 517 case ENUMS: return IJavaSearchConstants.ENUM; 518 case ANNOTATIONS: return IJavaSearchConstants.ANNOTATION_TYPE; 519 case CLASSES | INTERFACES: return IJavaSearchConstants.CLASS_AND_INTERFACE; 520 case CLASSES | ENUMS: return IJavaSearchConstants.CLASS_AND_ENUM; 521 default: return IJavaSearchConstants.TYPE; 522 } 523 } 524 525 private boolean isOfKind(TypeNameMatch curr, int typeKinds, boolean is50OrHigher) { 526 int flags= curr.getModifiers(); 527 if (Flags.isAnnotation(flags)) { 528 return is50OrHigher && ((typeKinds & SimilarElementsRequestor.ANNOTATIONS) != 0); 529 } 530 if (Flags.isEnum(flags)) { 531 return is50OrHigher && ((typeKinds & SimilarElementsRequestor.ENUMS) != 0); 532 } 533 if (Flags.isInterface(flags)) { 534 return (typeKinds & SimilarElementsRequestor.INTERFACES) != 0; 535 } 536 return (typeKinds & SimilarElementsRequestor.CLASSES) != 0; 537 } 538 539 540 private boolean isVisible(TypeNameMatch curr, ICompilationUnit cu) { 541 int flags= curr.getModifiers(); 542 if (Flags.isPrivate(flags)) { 543 return false; 544 } 545 if (Flags.isPublic(flags) || Flags.isProtected(flags)) { 546 return true; 547 } 548 return curr.getPackageName().equals(cu.getParent().getElementName()); 549 } 550 551 562 public static String evaluateTemplate(Template template, ICompilationUnit compilationUnit, int position) throws CoreException, BadLocationException, TemplateException { 563 564 TemplateContextType contextType= JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(JavaContextType.NAME); 565 if (contextType == null) 566 throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR, JavaTemplateMessages.JavaContext_error_message, null)); 567 568 IDocument document= new Document(); 569 if (compilationUnit != null && compilationUnit.exists()) 570 document.set(compilationUnit.getSource()); 571 572 JavaContext context= new JavaContext(contextType, document, position, 0, compilationUnit); 573 context.setForceEvaluation(true); 574 575 TemplateBuffer buffer= context.evaluate(template); 576 if (buffer == null) 577 return null; 578 return buffer.getString(); 579 } 580 581 TemplateVariable getTemplateVariable(String name) { 582 TemplateVariable variable= (TemplateVariable) fVariables.get(name); 583 if (variable != null && !variable.isResolved()) 584 getContextType().resolve(variable, this); 585 return variable; 586 } 587 588 596 public void addDependency(MultiVariable master, MultiVariable slave) { 597 MultiVariableGuess guess= getMultiVariableGuess(); 598 if (guess == null) { 599 guess= new MultiVariableGuess(); 600 setMultiVariableGuess(guess); 601 } 602 603 guess.addDependency(master, slave); 604 } 605 606 } 607 | Popular Tags |