1 /******************************************************************************* 2 * Copyright (c) 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Sebastian Davids: sdavids@gmx.de - see bug 25376 14 * Lukas Hanke <hanke@yatta.de> - [templates][content assist] Content assist for 'for' loop should suggest member variables - https://bugs.eclipse.org/117215 15 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 488432 16 * Microsoft Corporation - moved template related code to jdt.core.manipulation - https://bugs.eclipse.org/549989 17 *******************************************************************************/ 18 package org.eclipse.jdt.internal.corext.template.java; 19 20 import org.eclipse.jface.text.IDocument; 21 import org.eclipse.jface.text.Position; 22 import org.eclipse.jface.text.templates.DocumentTemplateContext; 23 import org.eclipse.jface.text.templates.GlobalTemplateVariables; 24 import org.eclipse.jface.text.templates.TemplateContext; 25 import org.eclipse.jface.text.templates.TemplateVariable; 26 import org.eclipse.jface.text.templates.TemplateVariableResolver; 27 28 import org.eclipse.jdt.core.ICompilationUnit; 29 import org.eclipse.jdt.core.IJavaProject; 30 31 import org.eclipse.jdt.internal.core.manipulation.StubUtility; 32 import org.eclipse.jdt.internal.corext.template.java.CompilationUnitCompletion.Variable; 33 34 import org.eclipse.jdt.internal.ui.text.template.contentassist.MultiVariable; 35 36 37 /** 38 * An abstract context type for templates inside Java code. 39 * 40 * @since 3.4 41 */ 42 public abstract class AbstractJavaContextTypeCore extends CompilationUnitContextType { 43 44 45 protected static abstract class AbstractIterable extends TemplateVariableResolver { AbstractIterable(String type, String description)46 public AbstractIterable(String type, String description) { 47 super(type, description); 48 } 49 50 @Override resolveAll(TemplateContext context)51 protected String[] resolveAll(TemplateContext context) { 52 IJavaContext jc= (IJavaContext) context; 53 Variable[] iterables= getVariables(jc); 54 String[] names= new String[iterables.length]; 55 for (int i= 0; i < iterables.length; i++) 56 names[i]= iterables[i].getName(); 57 if (names.length > 0) 58 jc.markAsUsed(names[0]); 59 return names; 60 } 61 getVariables(IJavaContext jc)62 abstract protected Variable[] getVariables(IJavaContext jc); 63 64 /* 65 * @see org.eclipse.jface.text.templates.TemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateVariable, org.eclipse.jface.text.templates.TemplateContext) 66 */ 67 @Override resolve(TemplateVariable variable, TemplateContext context)68 public void resolve(TemplateVariable variable, TemplateContext context) { 69 if (variable instanceof MultiVariable) { 70 IJavaContext jc= (IJavaContext) context; 71 JavaVariable jv= (JavaVariable) variable; 72 Variable[] iterables= getVariables(jc); 73 if (iterables.length > 0) { 74 jv.setChoices(iterables); 75 jc.markAsUsed(iterables[0].getName()); 76 77 if (iterables.length > 1) 78 variable.setUnambiguous(false); 79 else 80 variable.setUnambiguous(isUnambiguous(context)); 81 82 return; 83 } 84 } 85 86 super.resolve(variable, context); 87 } 88 } 89 90 protected static class Array extends AbstractIterable { Array()91 public Array() { 92 super("array", JavaTemplateMessages.JavaContextType_variable_description_array); //$NON-NLS-1$ 93 } 94 95 @Override getVariables(IJavaContext jc)96 protected Variable[] getVariables(IJavaContext jc) { 97 return jc.getArrays(); 98 } 99 } 100 101 protected static class Iterable extends AbstractIterable { Iterable()102 public Iterable() { 103 super("iterable", JavaTemplateMessages.JavaContextType_variable_description_iterable); //$NON-NLS-1$ 104 } 105 106 @Override getVariables(IJavaContext jc)107 protected Variable[] getVariables(IJavaContext jc) { 108 return jc.getIterables(); 109 } 110 } 111 112 protected static abstract class AbstractIterableType extends TemplateVariableResolver { 113 private String fMasterName; 114 AbstractIterableType(String type, String desc, String master)115 public AbstractIterableType(String type, String desc, String master) { 116 super(type, desc); 117 fMasterName= master; 118 } 119 @Override resolveAll(TemplateContext context)120 protected String[] resolveAll(TemplateContext context) { 121 IJavaContext jc= (IJavaContext) context; 122 Variable[] iterables= getVariablesInContextScope(jc); 123 String[] types= new String[iterables.length]; 124 for (int i= 0; i < iterables.length; i++) 125 types[i]= iterables[i].getMemberTypeNames()[0]; 126 return types; 127 } 128 getVariablesInContextScope(IJavaContext jc)129 abstract protected Variable[] getVariablesInContextScope(IJavaContext jc); 130 131 /* 132 * @see org.eclipse.jface.text.templates.TemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateVariable, org.eclipse.jface.text.templates.TemplateContext) 133 */ 134 @Override resolve(TemplateVariable variable, TemplateContext context)135 public void resolve(TemplateVariable variable, TemplateContext context) { 136 if (variable instanceof MultiVariable) { 137 IJavaContext jc= (IJavaContext) context; 138 MultiVariable mv= (MultiVariable) variable; 139 140 Variable[] iterables= getVariablesInContextScope(jc); 141 if (iterables.length > 0) { 142 143 for (Variable iterable : iterables) 144 mv.setChoices(iterable, iterable.getMemberTypeNames()); 145 146 TemplateVariable master= jc.getTemplateVariable(fMasterName); 147 if (master instanceof MultiVariable) { 148 final MultiVariable masterMv= (MultiVariable) master; 149 jc.addDependency(masterMv, mv); 150 mv.setKey(masterMv.getCurrentChoice()); 151 } 152 153 if (iterables.length > 1 || iterables.length == 1 && mv.getChoices().length > 1) 154 variable.setUnambiguous(false); 155 else 156 variable.setUnambiguous(isUnambiguous(context)); 157 158 return; 159 } 160 161 } 162 163 super.resolve(variable, context); 164 } 165 } 166 167 protected static class ArrayType extends AbstractIterableType { ArrayType()168 public ArrayType() { 169 super("array_type", JavaTemplateMessages.JavaContextType_variable_description_array_type, "array"); //$NON-NLS-1$ //$NON-NLS-2$ 170 } 171 @Override getVariablesInContextScope(IJavaContext jc)172 protected Variable[] getVariablesInContextScope(IJavaContext jc) { 173 return jc.getArrays(); 174 } 175 } 176 177 protected static class IterableType extends AbstractIterableType { IterableType()178 public IterableType() { 179 super("iterable_type", JavaTemplateMessages.JavaContextType_variable_description_iterable_type, "iterable"); //$NON-NLS-1$ //$NON-NLS-2$ 180 } 181 @Override getVariablesInContextScope(IJavaContext jc)182 protected Variable[] getVariablesInContextScope(IJavaContext jc) { 183 return jc.getIterables(); 184 } 185 } 186 187 protected static abstract class AbstractIterableElement extends TemplateVariableResolver { 188 private String fMasterName; 189 AbstractIterableElement(String type, String desc, String master)190 public AbstractIterableElement(String type, String desc, String master) { 191 super(type, desc); 192 fMasterName= master; 193 } 194 195 @Override resolveAll(TemplateContext context)196 protected String[] resolveAll(TemplateContext context) { 197 IJavaContext jc= (IJavaContext) context; 198 Variable[] iterables= getLocalVariables(jc); 199 String[] elements= new String[iterables.length]; 200 for (int i= 0; i < iterables.length; i++) { 201 elements[i]= jc.suggestVariableNames(iterables[i].getMemberTypeNames()[0])[0]; 202 if (i == 0) 203 jc.markAsUsed(elements[0]); 204 } 205 206 return elements; 207 } 208 getLocalVariables(IJavaContext jc)209 abstract protected Variable[] getLocalVariables(IJavaContext jc); 210 211 /* 212 * @see org.eclipse.jface.text.templates.TemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateVariable, org.eclipse.jface.text.templates.TemplateContext) 213 */ 214 @Override resolve(TemplateVariable variable, TemplateContext context)215 public void resolve(TemplateVariable variable, TemplateContext context) { 216 if (variable instanceof MultiVariable) { 217 IJavaContext jc= (IJavaContext) context; 218 MultiVariable mv= (MultiVariable) variable; 219 220 Variable[] iterables= getLocalVariables(jc); 221 if (iterables.length > 0) { 222 for (Variable iterable : iterables) { 223 String[] elements= jc.suggestVariableNames(iterable.getMemberTypeNames()[0]); 224 mv.setChoices(iterable, elements); 225 } 226 227 228 TemplateVariable master= jc.getTemplateVariable(fMasterName); 229 if (master instanceof MultiVariable) { 230 final MultiVariable masterMv= (MultiVariable) master; 231 jc.addDependency(masterMv, mv); 232 mv.setKey(masterMv.getCurrentChoice()); 233 } 234 jc.markAsUsed(mv.getDefaultValue()); 235 236 if (iterables.length > 1 || iterables.length == 1 && mv.getChoices().length > 1) 237 variable.setUnambiguous(false); 238 else 239 variable.setUnambiguous(isUnambiguous(context)); 240 241 return; 242 } 243 244 } 245 super.resolve(variable, context); 246 } 247 } 248 249 protected static class ArrayElement extends AbstractIterableElement { ArrayElement()250 public ArrayElement() { 251 super("array_element", JavaTemplateMessages.JavaContextType_variable_description_array_element, "array"); //$NON-NLS-1$ //$NON-NLS-2$ 252 } 253 @Override getLocalVariables(IJavaContext jc)254 protected Variable[] getLocalVariables(IJavaContext jc) { 255 return jc.getArrays(); 256 } 257 } 258 259 protected static class IterableElement extends AbstractIterableElement { IterableElement()260 public IterableElement() { 261 super("iterable_element", JavaTemplateMessages.JavaContextType_variable_description_iterable_element, "iterable"); //$NON-NLS-1$ //$NON-NLS-2$ 262 } 263 @Override getLocalVariables(IJavaContext jc)264 protected Variable[] getLocalVariables(IJavaContext jc) { 265 return jc.getIterables(); 266 } 267 } 268 269 protected static class Index extends NameResolver { Index()270 public Index() { 271 super("int"); //$NON-NLS-1$ 272 setType("index"); //$NON-NLS-1$ 273 setDescription(JavaTemplateMessages.JavaContextType_variable_description_index); 274 } 275 } 276 277 protected static class Collection extends VarResolver { Collection()278 public Collection() { 279 super("java.util.Collection"); //$NON-NLS-1$ 280 setType("collection"); //$NON-NLS-1$ 281 setDescription(JavaTemplateMessages.JavaContextType_variable_description_collection); 282 } 283 } 284 285 protected static class Iterator extends NameResolver { Iterator()286 public Iterator() { 287 super("java.util.Iterator"); //$NON-NLS-1$ 288 setType("iterator"); //$NON-NLS-1$ 289 setDescription(JavaTemplateMessages.JavaContextType_variable_description_iterator); 290 } 291 } 292 293 protected static class Todo extends TemplateVariableResolver { 294 Todo()295 public Todo() { 296 super("todo", JavaTemplateMessages.JavaContextType_variable_description_todo); //$NON-NLS-1$ 297 } 298 @Override resolve(TemplateContext context)299 protected String resolve(TemplateContext context) { 300 IJavaContext javaContext= (IJavaContext) context; 301 ICompilationUnit compilationUnit= javaContext.getCompilationUnit(); 302 if (compilationUnit == null) 303 return "XXX"; //$NON-NLS-1$ 304 305 IJavaProject javaProject= compilationUnit.getJavaProject(); 306 String todoTaskTag= StubUtility.getTodoTaskTag(javaProject); 307 if (todoTaskTag == null) 308 return "XXX"; //$NON-NLS-1$ 309 310 return todoTaskTag; 311 } 312 } 313 /* 314 protected static class Arguments extends SimpleVariableResolver { 315 public Arguments() { 316 super("arguments", TemplateMessages.getString("Javavariable.description.arguments"), ""); 317 } 318 } 319 */ 320 321 /** 322 * Initializes the context type resolvers. 323 * <p> 324 * <strong>Note:</strong> Only call this method if this 325 * context type doesn't inherit from another context type 326 * which already has these resolvers.</p> 327 * 328 * @since 3.4 329 */ initializeContextTypeResolvers()330 public void initializeContextTypeResolvers() { 331 332 // global 333 addResolver(new GlobalTemplateVariables.Cursor()); 334 addResolver(new GlobalTemplateVariables.WordSelection()); 335 addResolver(new GlobalTemplateVariables.Selection(GlobalTemplateVariables.LineSelection.NAME, JavaTemplateMessages.CompilationUnitContextType_variable_description_line_selection)); 336 addResolver(new GlobalTemplateVariables.Dollar()); 337 addResolver(new GlobalTemplateVariables.Date()); 338 addResolver(new GlobalTemplateVariables.Year()); 339 addResolver(new GlobalTemplateVariables.Time()); 340 addResolver(new GlobalTemplateVariables.User()); 341 342 // compilation unit 343 addResolver(new File()); 344 addResolver(new PrimaryTypeName()); 345 addResolver(new ReturnType()); 346 addResolver(new Method()); 347 addResolver(new Type()); 348 addResolver(new Package()); 349 addResolver(new Project()); 350 addResolver(new Arguments()); 351 352 // java 353 addResolver(new Array()); 354 addResolver(new ArrayType()); 355 addResolver(new ArrayElement()); 356 addResolver(new Index()); 357 addResolver(new Iterator()); 358 addResolver(new Collection()); 359 addResolver(new Iterable()); 360 addResolver(new IterableType()); 361 addResolver(new IterableElement()); 362 addResolver(new Todo()); 363 } 364 365 366 /* 367 * @see org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType#createContext(org.eclipse.jface.text.IDocument, int, int, org.eclipse.jdt.core.ICompilationUnit) 368 */ 369 @Override createContext(IDocument document, int offset, int length, ICompilationUnit compilationUnit)370 public DocumentTemplateContext createContext(IDocument document, int offset, int length, ICompilationUnit compilationUnit) { 371 JavaContextCore javaContext= new JavaContextCore(this, document, offset, length, compilationUnit); 372 initializeContext(javaContext); 373 return javaContext; 374 } 375 376 /* 377 * @see org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType#createContext(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position, org.eclipse.jdt.core.ICompilationUnit) 378 */ 379 @Override createContext(IDocument document, Position completionPosition, ICompilationUnit compilationUnit)380 public DocumentTemplateContext createContext(IDocument document, Position completionPosition, ICompilationUnit compilationUnit) { 381 JavaContextCore javaContext= new JavaContextCore(this, document, completionPosition, compilationUnit); 382 initializeContext(javaContext); 383 return javaContext; 384 } 385 386 /** 387 * Hook to initialize the context 388 * 389 * @param context the context 390 */ initializeContext(IJavaContext context)391 protected void initializeContext(IJavaContext context) { 392 } 393 394 } 395