1 /******************************************************************************* 2 * Copyright (c) 2000, 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 *******************************************************************************/ 14 package org.eclipse.jdt.core; 15 16 import org.eclipse.core.runtime.IProgressMonitor; 17 import org.eclipse.jdt.core.compiler.CharOperation; 18 import org.eclipse.jdt.internal.core.BufferManager; 19 import org.eclipse.jdt.internal.core.CompilationUnit; 20 import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner; 21 import org.eclipse.jdt.internal.core.ExternalJavaProject; 22 import org.eclipse.jdt.internal.core.PackageFragment; 23 import org.eclipse.jdt.internal.core.PackageFragmentRoot; 24 25 /** 26 * The owner of an {@link ICompilationUnit} handle in working copy mode. 27 * An owner is used to identify a working copy and to create its buffer. 28 * <p> 29 * Clients should subclass this class to instantiate a working copy owner that is specific to their need and that 30 * they can pass in to various APIs (e.g. {@link IType#resolveType(String, WorkingCopyOwner)}. 31 * Clients can also override the default implementation of {@link #createBuffer(ICompilationUnit)}. 32 * </p><p> 33 * Note: even though this class has no abstract method, which means that it provides functional default behavior, 34 * it is still an abstract class, as clients are intended to own their owner implementation. 35 * </p> 36 * @see ICompilationUnit#becomeWorkingCopy(org.eclipse.core.runtime.IProgressMonitor) 37 * @see ICompilationUnit#discardWorkingCopy() 38 * @see ICompilationUnit#getWorkingCopy(org.eclipse.core.runtime.IProgressMonitor) 39 * @since 3.0 40 */ 41 public abstract class WorkingCopyOwner { 42 43 /** 44 * Sets the buffer provider of the primary working copy owner. Note that even if the 45 * buffer provider is a working copy owner, only its <code>createBuffer(ICompilationUnit)</code> 46 * method is used by the primary working copy owner. It doesn't replace the internal primary 47 * working owner. 48 * <p> 49 * This method is for internal use by the jdt-related plug-ins. 50 * Clients outside of the jdt should not reference this method. 51 * </p> 52 * 53 * @param primaryBufferProvider the primary buffer provider 54 */ setPrimaryBufferProvider(WorkingCopyOwner primaryBufferProvider)55 public static void setPrimaryBufferProvider(WorkingCopyOwner primaryBufferProvider) { 56 DefaultWorkingCopyOwner.PRIMARY.primaryBufferProvider = primaryBufferProvider; 57 } 58 59 /** 60 * Creates a buffer for the given working copy. 61 * The new buffer will be initialized with the contents of the underlying file 62 * if and only if it was not already initialized by the compilation owner (a buffer is 63 * uninitialized if its content is <code>null</code>). 64 * <p> 65 * Note: This buffer will be associated to the working copy for its entire life-cycle. Another 66 * working copy on same unit but owned by a different owner would not share the same buffer 67 * unless its owner decided to implement such a sharing behaviour. 68 * </p> 69 * 70 * @param workingCopy the working copy of the buffer 71 * @return IBuffer the created buffer for the given working copy 72 * @see IBuffer 73 */ createBuffer(ICompilationUnit workingCopy)74 public IBuffer createBuffer(ICompilationUnit workingCopy) { 75 76 return BufferManager.createBuffer(workingCopy); 77 } 78 79 /** 80 * Returns the problem requestor used by a working copy of this working copy owner. 81 * <p> 82 * By default, no problem requestor is configured. Clients can override this 83 * method to provide a requestor. 84 * </p> 85 * 86 * @param workingCopy The problem requestor used for the given working copy. 87 * @return the problem requestor to be used by working copies of this working 88 * copy owner or <code>null</code> if no problem requestor is configured. 89 * 90 * @since 3.3 91 */ getProblemRequestor(ICompilationUnit workingCopy)92 public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) { 93 return null; 94 } 95 96 /** 97 * Returns the source of the compilation unit that defines the given type in 98 * the given package, or <code>null</code> if the type is unknown to this 99 * owner. 100 * <p>This method is called before the normal lookup (i.e. before looking 101 * at the project's classpath and before looking at the working copies of this 102 * owner.)</p> 103 * <p>This allows to provide types that are not normally available, or to hide 104 * types that would normally be available by returning an empty source for 105 * the given type and package.</p> 106 * <p>Example of use: 107 * <pre> 108 * WorkingCopyOwner owner = new WorkingCopyOwner() { 109 * public String findSource(String typeName, String packageName) { 110 * if ("to.be".equals(packageName) && "Generated".equals(typeName)) { 111 * return 112 * "package to.be;\n" + 113 * "public class Generated {\n" + 114 * "}"; 115 * } 116 * return super.findSource(typeName, packageName); 117 * } 118 * public boolean isPackage(String[] pkg) { 119 * switch (pkg.length) { 120 * case 1: 121 * return "to".equals(pkg[0]); 122 * case 2: 123 * return "to".equals(pkg[0]) && "be".equals(pkg[1]); 124 * } 125 * return false; 126 * } 127 * }; 128 * // Working copy on X.java with the following contents: 129 * // public class X extends to.be.Generated { 130 * // } 131 * ICompilationUnit workingCopy = ... 132 * ASTParser parser = ASTParser.newParser(AST.JLS3); 133 * parser.setSource(workingCopy); 134 * parser.setResolveBindings(true); 135 * parser.setWorkingCopyOwner(owner); 136 * CompilationUnit cu = (CompilationUnit) parser.createAST(null); 137 * assert cu.getProblems().length == 0; 138 * </pre> 139 * 140 * @param typeName the simple name of the type to lookup 141 * @param packageName the dot-separated name of the package of type 142 * @return the source of the compilation unit that defines the given type in 143 * the given package, or <code>null</code> if the type is unknown 144 * @see #isPackage(String[]) 145 * @since 3.5 146 */ findSource(String typeName, String packageName)147 public String findSource(String typeName, String packageName) { 148 return null; 149 } 150 151 /** 152 * Returns whether the given package segments represent a package. 153 * <p>This method is called before the normal lookup (i.e. before looking 154 * at the project's classpath and before looking at the working copies of this 155 * owner.)</p> 156 * <p>This allows to provide packages that are not normally available.</p> 157 * <p>If <code>false</code> is returned, then normal lookup is used on 158 * this package.</p> 159 * 160 * @param pkg the segments of a package to lookup 161 * @return whether the given package segments represent a package. 162 * @see #findSource(String, String) 163 * @since 3.5 164 */ isPackage(String[] pkg)165 public boolean isPackage(String[] pkg) { 166 return false; 167 } 168 169 /** 170 * Returns a new working copy with the given name using this working copy owner to 171 * create its buffer. 172 * <p> 173 * This working copy always belongs to the default package in a package 174 * fragment root that corresponds to its Java project, and this Java project never exists. 175 * However this Java project has the given classpath that is used when resolving names 176 * in this working copy. 177 * </p><p> 178 * A DOM AST created using this working copy will have bindings resolved using the given 179 * classpath, and problem are reported to the given problem requestor. 180 * </p><p> 181 * <code>JavaCore#getOptions()</code> is used to create the DOM AST as it is not 182 * possible to set the options on the non-existing Java project. 183 * </p><p> 184 * When the working copy instance is created, an {@link IJavaElementDelta#ADDED added delta} is 185 * reported on this working copy. 186 * </p><p> 187 * Once done with the working copy, users of this method must discard it using 188 * {@link ICompilationUnit#discardWorkingCopy()}. 189 * </p><p> 190 * Note that when such working copy is committed, only its buffer is saved (see 191 * {@link IBuffer#save(IProgressMonitor, boolean)}) but no resource is created. 192 * </p><p> 193 * This method is not intended to be overriden by clients. 194 * </p> 195 * 196 * @param name the name of the working copy (e.g. "X.java") 197 * @param classpath the classpath used to resolve names in this working copy 198 * @param problemRequestor a requestor which will get notified of problems detected during 199 * reconciling as they are discovered. The requestor can be set to <code>null</code> indicating 200 * that the client is not interested in problems. 201 * @param monitor a progress monitor used to report progress while opening the working copy 202 * or <code>null</code> if no progress should be reported 203 * @throws JavaModelException if the contents of this working copy can 204 * not be determined. 205 * @return a new working copy 206 * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor) 207 * @since 3.2 208 * 209 * @deprecated Use {@link #newWorkingCopy(String, IClasspathEntry[], IProgressMonitor)} instead. 210 * Note that if this deprecated method is used, problems may be reported twice 211 * if the given requestor is not the same as the current working copy owner one. 212 */ newWorkingCopy(String name, IClasspathEntry[] classpath, IProblemRequestor problemRequestor, IProgressMonitor monitor)213 public final ICompilationUnit newWorkingCopy(String name, IClasspathEntry[] classpath, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException { 214 ExternalJavaProject project = new ExternalJavaProject(classpath); 215 IPackageFragment parent = ((PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject())).getPackageFragment(CharOperation.NO_STRINGS); 216 CompilationUnit result = new CompilationUnit((PackageFragment) parent, name, this); 217 result.becomeWorkingCopy(problemRequestor, monitor); 218 return result; 219 } 220 221 /** 222 * Returns a new working copy with the given name using this working copy owner to 223 * create its buffer. 224 * <p> 225 * This working copy always belongs to the default package in a package 226 * fragment root that corresponds to its Java project, and this Java project never exists. 227 * However this Java project has the given classpath that is used when resolving names 228 * in this working copy. 229 * </p><p> 230 * If a DOM AST is created using this working copy, then given classpath will be used 231 * if bindings need to be resolved. Problems will be reported to the problem requestor 232 * of the current working copy owner problem if it is not <code>null</code>. 233 * </p><p> 234 * Options used to create the DOM AST are got from {@link JavaCore#getOptions()} 235 * as it is not possible to set the options on a non-existing Java project. 236 * </p><p> 237 * When the working copy instance is created, an {@link IJavaElementDelta#ADDED added delta} is 238 * reported on this working copy. 239 * </p><p> 240 * Once done with the working copy, users of this method must discard it using 241 * {@link ICompilationUnit#discardWorkingCopy()}. 242 * </p><p> 243 * Note that when such working copy is committed, only its buffer is saved (see 244 * {@link IBuffer#save(IProgressMonitor, boolean)}) but no resource is created. 245 * </p><p> 246 * This method is not intended to be overriden by clients. 247 * </p> 248 * 249 * @param name the name of the working copy (e.g. "X.java") 250 * @param classpath the classpath used to resolve names in this working copy 251 * @param monitor a progress monitor used to report progress while opening the working copy 252 * or <code>null</code> if no progress should be reported 253 * @throws JavaModelException if the contents of this working copy can 254 * not be determined. 255 * @return a new working copy 256 * @see ICompilationUnit#becomeWorkingCopy(IProgressMonitor) 257 * 258 * @since 3.3 259 */ newWorkingCopy(String name, IClasspathEntry[] classpath, IProgressMonitor monitor)260 public final ICompilationUnit newWorkingCopy(String name, IClasspathEntry[] classpath, IProgressMonitor monitor) throws JavaModelException { 261 ExternalJavaProject project = new ExternalJavaProject(classpath); 262 IPackageFragment parent = ((PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject())).getPackageFragment(CharOperation.NO_STRINGS); 263 CompilationUnit result = new CompilationUnit((PackageFragment) parent, name, this); 264 result.becomeWorkingCopy(getProblemRequestor(result), monitor); 265 return result; 266 } 267 268 } 269