feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.io.IOException;
import java.util.Collection;
import java.util.Locale;
import javax.annotation.processing.Processor;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.JavaFileObject;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
/**
* Provides basic functionality for implementations of JavacTask.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class BasicJavacTask extends JavacTask {
protected Context context;
private TaskListener taskListener;
public static JavacTask instance(Context context) {
JavacTask instance = context.get(JavacTask.class);
if (instance == null)
instance = new BasicJavacTask(context, true);
return instance;
}
public BasicJavacTask(Context c, boolean register) {
context = c;
if (register)
context.put(JavacTask.class, this);
}
@Override
public Iterable<? extends CompilationUnitTree> parse() throws IOException {
throw new IllegalStateException();
}
@Override
public Iterable<? extends Element> analyze() throws IOException {
throw new IllegalStateException();
}
@Override
public Iterable<? extends JavaFileObject> generate() throws IOException {
throw new IllegalStateException();
}
@Override
public void setTaskListener(TaskListener tl) {
MultiTaskListener mtl = MultiTaskListener.instance(context);
if (taskListener != null)
mtl.remove(taskListener);
if (tl != null)
mtl.add(tl);
taskListener = tl;
}
@Override
public void addTaskListener(TaskListener taskListener) {
MultiTaskListener mtl = MultiTaskListener.instance(context);
mtl.add(taskListener);
}
@Override
public void removeTaskListener(TaskListener taskListener) {
MultiTaskListener mtl = MultiTaskListener.instance(context);
mtl.remove(taskListener);
}
public Collection<TaskListener> getTaskListeners() {
MultiTaskListener mtl = MultiTaskListener.instance(context);
return mtl.getTaskListeners();
}
@Override
public TypeMirror getTypeMirror(Iterable<? extends Tree> path) {
// TODO: Should complete attribution if necessary
Tree last = null;
for (Tree node : path)
last = node;
return ((JCTree)last).type;
}
@Override
public Elements getElements() {
return JavacElements.instance(context);
}
@Override
public Types getTypes() {
return JavacTypes.instance(context);
}
public void setProcessors(Iterable<? extends Processor> processors) {
throw new IllegalStateException();
}
public void setLocale(Locale locale) {
throw new IllegalStateException();
}
public Boolean call() {
throw new IllegalStateException();
}
/**
* For internal use only. This method will be
* removed without warning.
*/
public Context getContext() {
return context;
}
/**
* For internal use only. This method will be
* removed without warning.
*/
public void updateContext(Context newContext) {
context = newContext;
}
}

View File

@@ -0,0 +1,698 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic;
/**
* Wrap objects to enable unchecked exceptions to be caught and handled.
*
* For each method, exceptions are handled as follows:
* <ul>
* <li>Checked exceptions are left alone and propogate upwards in the
* obvious way, since they are an expected aspect of the method's
* specification.
* <li>Unchecked exceptions which have already been caught and wrapped in
* ClientCodeException are left alone to continue propogating upwards.
* <li>All other unchecked exceptions (i.e. subtypes of RuntimeException
* and Error) and caught, and rethrown as a ClientCodeException with
* its cause set to the original exception.
* </ul>
*
* The intent is that ClientCodeException can be caught at an appropriate point
* in the program and can be distinguished from any unanticipated unchecked
* exceptions arising in the main body of the code (i.e. bugs.) When the
* ClientCodeException has been caught, either a suitable message can be
* generated, or if appropriate, the original cause can be rethrown.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class ClientCodeWrapper {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Trusted { }
public static ClientCodeWrapper instance(Context context) {
ClientCodeWrapper instance = context.get(ClientCodeWrapper.class);
if (instance == null)
instance = new ClientCodeWrapper(context);
return instance;
}
/**
* A map to cache the results of whether or not a specific classes can
* be "trusted", and thus does not need to be wrapped.
*/
Map<Class<?>, Boolean> trustedClasses;
protected ClientCodeWrapper(Context context) {
trustedClasses = new HashMap<Class<?>, Boolean>();
}
public JavaFileManager wrap(JavaFileManager fm) {
if (isTrusted(fm))
return fm;
return new WrappedJavaFileManager(fm);
}
public FileObject wrap(FileObject fo) {
if (isTrusted(fo))
return fo;
return new WrappedFileObject(fo);
}
FileObject unwrap(FileObject fo) {
if (fo instanceof WrappedFileObject)
return ((WrappedFileObject) fo).clientFileObject;
else
return fo;
}
public JavaFileObject wrap(JavaFileObject fo) {
if (isTrusted(fo))
return fo;
return new WrappedJavaFileObject(fo);
}
public Iterable<JavaFileObject> wrapJavaFileObjects(Iterable<? extends JavaFileObject> list) {
List<JavaFileObject> wrapped = new ArrayList<JavaFileObject>();
for (JavaFileObject fo : list)
wrapped.add(wrap(fo));
return Collections.unmodifiableList(wrapped);
}
JavaFileObject unwrap(JavaFileObject fo) {
if (fo instanceof WrappedJavaFileObject)
return ((JavaFileObject) ((WrappedJavaFileObject) fo).clientFileObject);
else
return fo;
}
public <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
if (isTrusted(dl))
return dl;
return new WrappedDiagnosticListener<T>(dl);
}
TaskListener wrap(TaskListener tl) {
if (isTrusted(tl))
return tl;
return new WrappedTaskListener(tl);
}
TaskListener unwrap(TaskListener l) {
if (l instanceof WrappedTaskListener)
return ((WrappedTaskListener) l).clientTaskListener;
else
return l;
}
Collection<TaskListener> unwrap(Collection<? extends TaskListener> listeners) {
Collection<TaskListener> c = new ArrayList<TaskListener>(listeners.size());
for (TaskListener l: listeners)
c.add(unwrap(l));
return c;
}
@SuppressWarnings("unchecked")
private <T> Diagnostic<T> unwrap(final Diagnostic<T> diagnostic) {
if (diagnostic instanceof JCDiagnostic) {
JCDiagnostic d = (JCDiagnostic) diagnostic;
return (Diagnostic<T>) new DiagnosticSourceUnwrapper(d);
} else {
return diagnostic;
}
}
protected boolean isTrusted(Object o) {
Class<?> c = o.getClass();
Boolean trusted = trustedClasses.get(c);
if (trusted == null) {
trusted = c.getName().startsWith("com.sun.tools.javac.")
|| c.isAnnotationPresent(Trusted.class);
trustedClasses.put(c, trusted);
}
return trusted;
}
private String wrappedToString(Class<?> wrapperClass, Object wrapped) {
return wrapperClass.getSimpleName() + "[" + wrapped + "]";
}
// <editor-fold defaultstate="collapsed" desc="Wrapper classes">
// FIXME: all these classes should be converted to use multi-catch when
// that is available in the bootstrap compiler.
protected class WrappedJavaFileManager implements JavaFileManager {
protected JavaFileManager clientJavaFileManager;
WrappedJavaFileManager(JavaFileManager clientJavaFileManager) {
clientJavaFileManager.getClass(); // null check
this.clientJavaFileManager = clientJavaFileManager;
}
@Override
public ClassLoader getClassLoader(Location location) {
try {
return clientJavaFileManager.getClassLoader(location);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
try {
return wrapJavaFileObjects(clientJavaFileManager.list(location, packageName, kinds, recurse));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String inferBinaryName(Location location, JavaFileObject file) {
try {
return clientJavaFileManager.inferBinaryName(location, unwrap(file));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public boolean isSameFile(FileObject a, FileObject b) {
try {
return clientJavaFileManager.isSameFile(unwrap(a), unwrap(b));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public boolean handleOption(String current, Iterator<String> remaining) {
try {
return clientJavaFileManager.handleOption(current, remaining);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public boolean hasLocation(Location location) {
try {
return clientJavaFileManager.hasLocation(location);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
try {
return wrap(clientJavaFileManager.getJavaFileForInput(location, className, kind));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
try {
return wrap(clientJavaFileManager.getJavaFileForOutput(location, className, kind, unwrap(sibling)));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
try {
return wrap(clientJavaFileManager.getFileForInput(location, packageName, relativeName));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
try {
return wrap(clientJavaFileManager.getFileForOutput(location, packageName, relativeName, unwrap(sibling)));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public void flush() throws IOException {
try {
clientJavaFileManager.flush();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public void close() throws IOException {
try {
clientJavaFileManager.close();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public int isSupportedOption(String option) {
try {
return clientJavaFileManager.isSupportedOption(option);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String toString() {
return wrappedToString(getClass(), clientJavaFileManager);
}
}
protected class WrappedFileObject implements FileObject {
protected FileObject clientFileObject;
WrappedFileObject(FileObject clientFileObject) {
clientFileObject.getClass(); // null check
this.clientFileObject = clientFileObject;
}
@Override
public URI toUri() {
try {
return clientFileObject.toUri();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String getName() {
try {
return clientFileObject.getName();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public InputStream openInputStream() throws IOException {
try {
return clientFileObject.openInputStream();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public OutputStream openOutputStream() throws IOException {
try {
return clientFileObject.openOutputStream();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
try {
return clientFileObject.openReader(ignoreEncodingErrors);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
try {
return clientFileObject.getCharContent(ignoreEncodingErrors);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public Writer openWriter() throws IOException {
try {
return clientFileObject.openWriter();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public long getLastModified() {
try {
return clientFileObject.getLastModified();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public boolean delete() {
try {
return clientFileObject.delete();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String toString() {
return wrappedToString(getClass(), clientFileObject);
}
}
protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
WrappedJavaFileObject(JavaFileObject clientJavaFileObject) {
super(clientJavaFileObject);
}
@Override
public Kind getKind() {
try {
return ((JavaFileObject)clientFileObject).getKind();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public boolean isNameCompatible(String simpleName, Kind kind) {
try {
return ((JavaFileObject)clientFileObject).isNameCompatible(simpleName, kind);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public NestingKind getNestingKind() {
try {
return ((JavaFileObject)clientFileObject).getNestingKind();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public Modifier getAccessLevel() {
try {
return ((JavaFileObject)clientFileObject).getAccessLevel();
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String toString() {
return wrappedToString(getClass(), clientFileObject);
}
}
protected class WrappedDiagnosticListener<T /*super JavaFileObject*/> implements DiagnosticListener<T> {
protected DiagnosticListener<T> clientDiagnosticListener;
WrappedDiagnosticListener(DiagnosticListener<T> clientDiagnosticListener) {
clientDiagnosticListener.getClass(); // null check
this.clientDiagnosticListener = clientDiagnosticListener;
}
@Override
public void report(Diagnostic<? extends T> diagnostic) {
try {
clientDiagnosticListener.report(unwrap(diagnostic));
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String toString() {
return wrappedToString(getClass(), clientDiagnosticListener);
}
}
public class DiagnosticSourceUnwrapper implements Diagnostic<JavaFileObject> {
public final JCDiagnostic d;
DiagnosticSourceUnwrapper(JCDiagnostic d) {
this.d = d;
}
public Diagnostic.Kind getKind() {
return d.getKind();
}
public JavaFileObject getSource() {
return unwrap(d.getSource());
}
public long getPosition() {
return d.getPosition();
}
public long getStartPosition() {
return d.getStartPosition();
}
public long getEndPosition() {
return d.getEndPosition();
}
public long getLineNumber() {
return d.getLineNumber();
}
public long getColumnNumber() {
return d.getColumnNumber();
}
public String getCode() {
return d.getCode();
}
public String getMessage(Locale locale) {
return d.getMessage(locale);
}
@Override
public String toString() {
return d.toString();
}
}
protected class WrappedTaskListener implements TaskListener {
protected TaskListener clientTaskListener;
WrappedTaskListener(TaskListener clientTaskListener) {
clientTaskListener.getClass(); // null check
this.clientTaskListener = clientTaskListener;
}
@Override
public void started(TaskEvent ev) {
try {
clientTaskListener.started(ev);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public void finished(TaskEvent ev) {
try {
clientTaskListener.finished(ev);
} catch (ClientCodeException e) {
throw e;
} catch (RuntimeException e) {
throw new ClientCodeException(e);
} catch (Error e) {
throw new ClientCodeException(e);
}
}
@Override
public String toString() {
return wrappedToString(getClass(), clientTaskListener);
}
}
// </editor-fold>
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.util.Locale;
import java.util.Set;
import javax.tools.Diagnostic;
import com.sun.tools.javac.api.DiagnosticFormatter.*;
/**
* Provides simple functionalities for javac diagnostic formatting.
* @param <D> type of diagnostic handled by this formatter
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public interface DiagnosticFormatter<D extends Diagnostic<?>> {
/**
* Whether the source code output for this diagnostic is to be displayed.
*
* @param diag diagnostic to be formatted
* @return true if the source line this diagnostic refers to is to be displayed
*/
boolean displaySource(D diag);
/**
* Format the contents of a diagnostics.
*
* @param diag the diagnostic to be formatted
* @param l locale object to be used for i18n
* @return a string representing the diagnostic
*/
public String format(D diag, Locale l);
/**
* Controls the way in which a diagnostic message is displayed.
*
* @param diag diagnostic to be formatted
* @param l locale object to be used for i18n
* @return string representation of the diagnostic message
*/
public String formatMessage(D diag,Locale l);
/**
* Controls the way in which a diagnostic kind is displayed.
*
* @param diag diagnostic to be formatted
* @param l locale object to be used for i18n
* @return string representation of the diagnostic prefix
*/
public String formatKind(D diag, Locale l);
/**
* Controls the way in which a diagnostic source is displayed.
*
* @param diag diagnostic to be formatted
* @param l locale object to be used for i18n
* @param fullname whether the source fullname should be printed
* @return string representation of the diagnostic source
*/
public String formatSource(D diag, boolean fullname, Locale l);
/**
* Controls the way in which a diagnostic position is displayed.
*
* @param diag diagnostic to be formatted
* @param pk enum constant representing the position kind
* @param l locale object to be used for i18n
* @return string representation of the diagnostic position
*/
public String formatPosition(D diag, PositionKind pk, Locale l);
//where
/**
* This enum defines a set of constants for all the kinds of position
* that a diagnostic can be asked for. All positions are intended to be
* relative to a given diagnostic source.
*/
public enum PositionKind {
/**
* Start position
*/
START,
/**
* End position
*/
END,
/**
* Line number
*/
LINE,
/**
* Column number
*/
COLUMN,
/**
* Offset position
*/
OFFSET
}
/**
* Get a list of all the enabled verbosity options.
* @return verbosity options
*/
public Configuration getConfiguration();
//where
/**
* This interface provides functionalities for tuning the output of a
* diagnostic formatter in multiple ways.
*/
interface Configuration {
/**
* Configure the set of diagnostic parts that should be displayed
* by the formatter.
* @param visibleParts the parts to be set
*/
public void setVisible(Set<DiagnosticPart> visibleParts);
/**
* Retrieve the set of diagnostic parts that should be displayed
* by the formatter.
* @return verbosity options
*/
public Set<DiagnosticPart> getVisible();
//where
/**
* A given diagnostic message can be divided into sub-parts each of which
* might/might not be displayed by the formatter, according to the
* current configuration settings.
*/
public enum DiagnosticPart {
/**
* Short description of the diagnostic - usually one line long.
*/
SUMMARY,
/**
* Longer description that provides additional details w.r.t. the ones
* in the diagnostic's description.
*/
DETAILS,
/**
* Source line the diagnostic refers to (if applicable).
*/
SOURCE,
/**
* Subdiagnostics attached to a given multiline diagnostic.
*/
SUBDIAGNOSTICS,
/**
* JLS paragraph this diagnostic might refer to (if applicable).
*/
JLS;
}
/**
* Set a limit for multiline diagnostics.
* Note: Setting a limit has no effect if multiline diagnostics are either
* fully enabled or disabled.
*
* @param limit the kind of limit to be set
* @param value the limit value
*/
public void setMultilineLimit(MultilineLimit limit, int value);
/**
* Get a multiline diagnostic limit.
*
* @param limit the kind of limit to be retrieved
* @return limit value or -1 if no limit is set
*/
public int getMultilineLimit(MultilineLimit limit);
//where
/**
* A multiline limit control the verbosity of multiline diagnostics
* either by setting a maximum depth of nested multidiagnostics,
* or by limiting the amount of subdiagnostics attached to a given
* diagnostic (or both).
*/
public enum MultilineLimit {
/**
* Controls the maximum depth of nested multiline diagnostics.
*/
DEPTH,
/**
* Controls the maximum amount of subdiagnostics that are part of a
* given multiline diagnostic.
*/
LENGTH;
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.util.Locale;
/**
* This interface must be implemented by any javac class that has non-trivial
* formatting needs (e.g. where toString() does not apply because of localization).
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*
* @author Maurizio Cimadamore
*/
public interface Formattable {
/**
* Used to obtain a localized String representing the object accordingly
* to a given locale
*
* @param locale locale in which the object's representation is to be rendered
* @param messages messages object used for localization
* @return a locale-dependent string representing the object
*/
public String toString(Locale locale, Messages messages);
/**
* Retrieve a pretty name of this object's kind
* @return a string representing the object's kind
*/
String getKind();
static class LocalizedString implements Formattable {
String key;
public LocalizedString(String key) {
this.key = key;
}
public String toString(java.util.Locale l, Messages messages) {
return messages.getLocalizedString(l, key);
}
public String getKind() {
return "LocalizedString";
}
public String toString() {
return key;
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
/**
* Provides an implementation of Scope.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Jonathan Gibbons;
*/
public class JavacScope implements com.sun.source.tree.Scope {
protected final Env<AttrContext> env;
/** Creates a new instance of JavacScope */
JavacScope(Env<AttrContext> env) {
env.getClass(); // null-check
this.env = env;
}
public JavacScope getEnclosingScope() {
if (env.outer != null && env.outer != env)
return new JavacScope(env.outer);
else {
// synthesize an outermost "star-import" scope
return new JavacScope(env) {
public boolean isStarImportScope() {
return true;
}
public JavacScope getEnclosingScope() {
return null;
}
public Iterable<? extends Element> getLocalElements() {
return env.toplevel.starImportScope.getElements();
}
};
}
}
public TypeElement getEnclosingClass() {
// hide the dummy class that javac uses to enclose the top level declarations
return (env.outer == null || env.outer == env ? null : env.enclClass.sym);
}
public ExecutableElement getEnclosingMethod() {
return (env.enclMethod == null ? null : env.enclMethod.sym);
}
public Iterable<? extends Element> getLocalElements() {
return env.info.getLocalElements();
}
public Env<AttrContext> getEnv() {
return env;
}
public boolean isStarImportScope() {
return false;
}
public boolean equals(Object other) {
if (other instanceof JavacScope) {
JavacScope s = (JavacScope) other;
return (env.equals(s.env)
&& isStarImportScope() == s.isStarImportScope());
} else
return false;
}
public int hashCode() {
return env.hashCode() + (isStarImportScope() ? 1 : 0);
}
public String toString() {
return "JavacScope[env=" + env + ",starImport=" + isStarImportScope() + "]";
}
}

View File

@@ -0,0 +1,512 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.io.File;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.processing.Processor;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.*;
import com.sun.source.tree.*;
import com.sun.source.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.*;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.model.*;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
/**
* Provides access to functionality specific to the JDK Java Compiler, javac.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Peter von der Ah&eacute;
* @author Jonathan Gibbons
*/
public class JavacTaskImpl extends BasicJavacTask {
private Main compilerMain;
private JavaCompiler compiler;
private Locale locale;
private String[] args;
private String[] classNames;
private List<JavaFileObject> fileObjects;
private Map<JavaFileObject, JCCompilationUnit> notYetEntered;
private ListBuffer<Env<AttrContext>> genList;
private final AtomicBoolean used = new AtomicBoolean();
private Iterable<? extends Processor> processors;
private Main.Result result = null;
JavacTaskImpl(Main compilerMain,
String[] args,
String[] classNames,
Context context,
List<JavaFileObject> fileObjects) {
super(null, false);
this.compilerMain = compilerMain;
this.args = args;
this.classNames = classNames;
this.context = context;
this.fileObjects = fileObjects;
setLocale(Locale.getDefault());
// null checks
compilerMain.getClass();
args.getClass();
fileObjects.getClass();
}
JavacTaskImpl(Main compilerMain,
Iterable<String> args,
Context context,
Iterable<String> classes,
Iterable<? extends JavaFileObject> fileObjects) {
this(compilerMain, toArray(args), toArray(classes), context, toList(fileObjects));
}
static private String[] toArray(Iterable<String> iter) {
ListBuffer<String> result = new ListBuffer<String>();
if (iter != null)
for (String s : iter)
result.append(s);
return result.toArray(new String[result.length()]);
}
static private List<JavaFileObject> toList(Iterable<? extends JavaFileObject> fileObjects) {
if (fileObjects == null)
return List.nil();
ListBuffer<JavaFileObject> result = new ListBuffer<JavaFileObject>();
for (JavaFileObject fo : fileObjects)
result.append(fo);
return result.toList();
}
public Main.Result doCall() {
if (!used.getAndSet(true)) {
initContext();
notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>();
compilerMain.setAPIMode(true);
result = compilerMain.compile(args, classNames, context, fileObjects, processors);
cleanup();
return result;
} else {
throw new IllegalStateException("multiple calls to method 'call'");
}
}
public Boolean call() {
return doCall().isOK();
}
public void setProcessors(Iterable<? extends Processor> processors) {
processors.getClass(); // null check
// not mt-safe
if (used.get())
throw new IllegalStateException();
this.processors = processors;
}
public void setLocale(Locale locale) {
if (used.get())
throw new IllegalStateException();
this.locale = locale;
}
private void prepareCompiler() throws IOException {
if (used.getAndSet(true)) {
if (compiler == null)
throw new IllegalStateException();
} else {
initContext();
compilerMain.log = Log.instance(context);
compilerMain.setOptions(Options.instance(context));
compilerMain.filenames = new LinkedHashSet<File>();
Collection<File> filenames = compilerMain.processArgs(CommandLine.parse(args), classNames);
if (filenames != null && !filenames.isEmpty())
throw new IllegalArgumentException("Malformed arguments " + toString(filenames, " "));
compiler = JavaCompiler.instance(context);
compiler.keepComments = true;
compiler.genEndPos = true;
// NOTE: this value will be updated after annotation processing
compiler.initProcessAnnotations(processors);
notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>();
for (JavaFileObject file: fileObjects)
notYetEntered.put(file, null);
genList = new ListBuffer<Env<AttrContext>>();
// endContext will be called when all classes have been generated
// TODO: should handle the case after each phase if errors have occurred
args = null;
classNames = null;
}
}
<T> String toString(Iterable<T> items, String sep) {
String currSep = "";
StringBuilder sb = new StringBuilder();
for (T item: items) {
sb.append(currSep);
sb.append(item.toString());
currSep = sep;
}
return sb.toString();
}
private void initContext() {
context.put(JavacTask.class, this);
//initialize compiler's default locale
context.put(Locale.class, locale);
}
void cleanup() {
if (compiler != null)
compiler.close();
compiler = null;
compilerMain = null;
args = null;
classNames = null;
context = null;
fileObjects = null;
notYetEntered = null;
}
/**
* Construct a JavaFileObject from the given file.
*
* <p><b>TODO: this method is useless here</b></p>
*
* @param file a file
* @return a JavaFileObject from the standard file manager.
*/
public JavaFileObject asJavaFileObject(File file) {
JavacFileManager fm = (JavacFileManager)context.get(JavaFileManager.class);
return fm.getRegularFile(file);
}
/**
* Parse the specified files returning a list of abstract syntax trees.
*
* @throws java.io.IOException TODO
* @return a list of abstract syntax trees
*/
public Iterable<? extends CompilationUnitTree> parse() throws IOException {
try {
prepareCompiler();
List<JCCompilationUnit> units = compiler.parseFiles(fileObjects);
for (JCCompilationUnit unit: units) {
JavaFileObject file = unit.getSourceFile();
if (notYetEntered.containsKey(file))
notYetEntered.put(file, unit);
}
return units;
}
finally {
parsed = true;
if (compiler != null && compiler.log != null)
compiler.log.flush();
}
}
private boolean parsed = false;
/**
* Translate all the abstract syntax trees to elements.
*
* @throws IOException TODO
* @return a list of elements corresponding to the top level
* classes in the abstract syntax trees
*/
public Iterable<? extends TypeElement> enter() throws IOException {
return enter(null);
}
/**
* Translate the given abstract syntax trees to elements.
*
* @param trees a list of abstract syntax trees.
* @throws java.io.IOException TODO
* @return a list of elements corresponding to the top level
* classes in the abstract syntax trees
*/
public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees)
throws IOException
{
if (trees == null && notYetEntered != null && notYetEntered.isEmpty())
return List.nil();
prepareCompiler();
ListBuffer<JCCompilationUnit> roots = null;
if (trees == null) {
// If there are still files which were specified to be compiled
// (i.e. in fileObjects) but which have not yet been entered,
// then we make sure they have been parsed and add them to the
// list to be entered.
if (notYetEntered.size() > 0) {
if (!parsed)
parse(); // TODO would be nice to specify files needed to be parsed
for (JavaFileObject file: fileObjects) {
JCCompilationUnit unit = notYetEntered.remove(file);
if (unit != null) {
if (roots == null)
roots = new ListBuffer<JCCompilationUnit>();
roots.append(unit);
}
}
notYetEntered.clear();
}
}
else {
for (CompilationUnitTree cu : trees) {
if (cu instanceof JCCompilationUnit) {
if (roots == null)
roots = new ListBuffer<JCCompilationUnit>();
roots.append((JCCompilationUnit)cu);
notYetEntered.remove(cu.getSourceFile());
}
else
throw new IllegalArgumentException(cu.toString());
}
}
if (roots == null)
return List.nil();
try {
List<JCCompilationUnit> units = compiler.enterTrees(roots.toList());
if (notYetEntered.isEmpty())
compiler = compiler.processAnnotations(units);
ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>();
for (JCCompilationUnit unit : units) {
for (JCTree node : unit.defs) {
if (node.hasTag(JCTree.Tag.CLASSDEF)) {
JCClassDecl cdef = (JCClassDecl) node;
if (cdef.sym != null) // maybe null if errors in anno processing
elements.append(cdef.sym);
}
}
}
return elements.toList();
}
finally {
compiler.log.flush();
}
}
/**
* Complete all analysis.
* @throws IOException TODO
*/
@Override
public Iterable<? extends Element> analyze() throws IOException {
return analyze(null);
}
/**
* Complete all analysis on the given classes.
* This can be used to ensure that all compile time errors are reported.
* The classes must have previously been returned from {@link #enter}.
* If null is specified, all outstanding classes will be analyzed.
*
* @param classes a list of class elements
*/
// This implementation requires that we open up privileges on JavaCompiler.
// An alternative implementation would be to move this code to JavaCompiler and
// wrap it here
public Iterable<? extends Element> analyze(Iterable<? extends TypeElement> classes) throws IOException {
enter(null); // ensure all classes have been entered
final ListBuffer<Element> results = new ListBuffer<Element>();
try {
if (classes == null) {
handleFlowResults(compiler.flow(compiler.attribute(compiler.todo)), results);
} else {
Filter f = new Filter() {
public void process(Env<AttrContext> env) {
handleFlowResults(compiler.flow(compiler.attribute(env)), results);
}
};
f.run(compiler.todo, classes);
}
} finally {
compiler.log.flush();
}
return results;
}
// where
private void handleFlowResults(Queue<Env<AttrContext>> queue, ListBuffer<Element> elems) {
for (Env<AttrContext> env: queue) {
switch (env.tree.getTag()) {
case CLASSDEF:
JCClassDecl cdef = (JCClassDecl) env.tree;
if (cdef.sym != null)
elems.append(cdef.sym);
break;
case TOPLEVEL:
JCCompilationUnit unit = (JCCompilationUnit) env.tree;
if (unit.packge != null)
elems.append(unit.packge);
break;
}
}
genList.addAll(queue);
}
/**
* Generate code.
* @throws IOException TODO
*/
@Override
public Iterable<? extends JavaFileObject> generate() throws IOException {
return generate(null);
}
/**
* Generate code corresponding to the given classes.
* The classes must have previously been returned from {@link #enter}.
* If there are classes outstanding to be analyzed, that will be done before
* any classes are generated.
* If null is specified, code will be generated for all outstanding classes.
*
* @param classes a list of class elements
*/
public Iterable<? extends JavaFileObject> generate(Iterable<? extends TypeElement> classes) throws IOException {
final ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
try {
analyze(null); // ensure all classes have been parsed, entered, and analyzed
if (classes == null) {
compiler.generate(compiler.desugar(genList), results);
genList.clear();
}
else {
Filter f = new Filter() {
public void process(Env<AttrContext> env) {
compiler.generate(compiler.desugar(ListBuffer.of(env)), results);
}
};
f.run(genList, classes);
}
if (genList.isEmpty()) {
compiler.reportDeferredDiagnostics();
cleanup();
}
}
finally {
if (compiler != null)
compiler.log.flush();
}
return results;
}
public TypeMirror getTypeMirror(Iterable<? extends Tree> path) {
// TODO: Should complete attribution if necessary
Tree last = null;
for (Tree node : path)
last = node;
return ((JCTree)last).type;
}
public JavacElements getElements() {
if (context == null)
throw new IllegalStateException();
return JavacElements.instance(context);
}
public JavacTypes getTypes() {
if (context == null)
throw new IllegalStateException();
return JavacTypes.instance(context);
}
public Iterable<? extends Tree> pathFor(CompilationUnitTree unit, Tree node) {
return TreeInfo.pathFor((JCTree) node, (JCTree.JCCompilationUnit) unit).reverse();
}
abstract class Filter {
void run(Queue<Env<AttrContext>> list, Iterable<? extends TypeElement> classes) {
Set<TypeElement> set = new HashSet<TypeElement>();
for (TypeElement item: classes)
set.add(item);
ListBuffer<Env<AttrContext>> defer = new ListBuffer<>();
while (list.peek() != null) {
Env<AttrContext> env = list.remove();
ClassSymbol csym = env.enclClass.sym;
if (csym != null && set.contains(csym.outermostClass()))
process(env);
else
defer = defer.append(env);
}
list.addAll(defer);
}
abstract void process(Env<AttrContext> env);
}
/**
* For internal use only. This method will be
* removed without warning.
*/
public Type parseType(String expr, TypeElement scope) {
if (expr == null || expr.equals(""))
throw new IllegalArgumentException();
compiler = JavaCompiler.instance(context);
JavaFileObject prev = compiler.log.useSource(null);
ParserFactory parserFactory = ParserFactory.instance(context);
Attr attr = Attr.instance(context);
try {
CharBuffer buf = CharBuffer.wrap((expr+"\u0000").toCharArray(), 0, expr.length());
Parser parser = parserFactory.newParser(buf, false, false, false);
JCTree tree = parser.parseType();
return attr.attribType(tree, (Symbol.TypeSymbol)scope);
} finally {
compiler.log.useSource(prev);
}
}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.tools.*;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.PrefixKind;
import com.sun.tools.javac.util.Options;
/**
* TODO: describe com.sun.tools.javac.api.Tool
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Peter von der Ah\u00e9
*/
public final class JavacTool implements JavaCompiler {
/**
* Constructor used by service provider mechanism. The recommended way to
* obtain an instance of this class is by using {@link #create} or the
* service provider mechanism.
* @see javax.tools.JavaCompiler
* @see javax.tools.ToolProvider
* @see #create
*/
@Deprecated
public JavacTool() {}
/**
* Static factory method for creating new instances of this tool.
* @return new instance of this tool
*/
public static JavacTool create() {
return new JavacTool();
}
public JavacFileManager getStandardFileManager(
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Locale locale,
Charset charset) {
Context context = new Context();
context.put(Locale.class, locale);
if (diagnosticListener != null)
context.put(DiagnosticListener.class, diagnosticListener);
PrintWriter pw = (charset == null)
? new PrintWriter(System.err, true)
: new PrintWriter(new OutputStreamWriter(System.err, charset), true);
context.put(Log.outKey, pw);
return new JavacFileManager(context, true, charset);
}
@Override
public JavacTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits) {
Context context = new Context();
return getTask(out, fileManager, diagnosticListener,
options, classes, compilationUnits,
context);
}
public JavacTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits,
Context context)
{
try {
ClientCodeWrapper ccw = ClientCodeWrapper.instance(context);
if (options != null)
for (String option : options)
option.getClass(); // null check
if (classes != null) {
for (String cls : classes)
if (!SourceVersion.isName(cls)) // implicit null check
throw new IllegalArgumentException("Not a valid class name: " + cls);
}
if (compilationUnits != null) {
compilationUnits = ccw.wrapJavaFileObjects(compilationUnits); // implicit null check
for (JavaFileObject cu : compilationUnits) {
if (cu.getKind() != JavaFileObject.Kind.SOURCE) {
String kindMsg = "Compilation unit is not of SOURCE kind: "
+ "\"" + cu.getName() + "\"";
throw new IllegalArgumentException(kindMsg);
}
}
}
if (diagnosticListener != null)
context.put(DiagnosticListener.class, ccw.wrap(diagnosticListener));
if (out == null)
context.put(Log.outKey, new PrintWriter(System.err, true));
else
context.put(Log.outKey, new PrintWriter(out, true));
if (fileManager == null)
fileManager = getStandardFileManager(diagnosticListener, null, null);
fileManager = ccw.wrap(fileManager);
context.put(JavaFileManager.class, fileManager);
processOptions(context, fileManager, options);
Main compiler = new Main("javacTask", context.get(Log.outKey));
return new JavacTaskImpl(compiler, options, context, classes, compilationUnits);
} catch (ClientCodeException ex) {
throw new RuntimeException(ex.getCause());
}
}
public static void processOptions(Context context,
JavaFileManager fileManager,
Iterable<String> options)
{
if (options == null)
return;
final Options optionTable = Options.instance(context);
Log log = Log.instance(context);
Option[] recognizedOptions =
Option.getJavacToolOptions().toArray(new Option[0]);
OptionHelper optionHelper = new GrumpyHelper(log) {
@Override
public String get(Option option) {
return optionTable.get(option.getText());
}
@Override
public void put(String name, String value) {
optionTable.put(name, value);
}
@Override
public void remove(String name) {
optionTable.remove(name);
}
};
Iterator<String> flags = options.iterator();
while (flags.hasNext()) {
String flag = flags.next();
int j;
for (j=0; j<recognizedOptions.length; j++)
if (recognizedOptions[j].matches(flag))
break;
if (j == recognizedOptions.length) {
if (fileManager.handleOption(flag, flags)) {
continue;
} else {
String msg = log.localize(PrefixKind.JAVAC, "err.invalid.flag", flag);
throw new IllegalArgumentException(msg);
}
}
Option option = recognizedOptions[j];
if (option.hasArg()) {
if (!flags.hasNext()) {
String msg = log.localize(PrefixKind.JAVAC, "err.req.arg", flag);
throw new IllegalArgumentException(msg);
}
String operand = flags.next();
if (option.process(optionHelper, flag, operand))
// should not happen as the GrumpyHelper will throw exceptions
// in case of errors
throw new IllegalArgumentException(flag + " " + operand);
} else {
if (option.process(optionHelper, flag))
// should not happen as the GrumpyHelper will throw exceptions
// in case of errors
throw new IllegalArgumentException(flag);
}
}
optionTable.notifyListeners();
}
public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) {
if (err == null)
err = System.err;
for (String argument : arguments)
argument.getClass(); // null check
return com.sun.tools.javac.Main.compile(arguments, new PrintWriter(err, true));
}
public Set<SourceVersion> getSourceVersions() {
return Collections.unmodifiableSet(EnumSet.range(SourceVersion.RELEASE_3,
SourceVersion.latest()));
}
public int isSupportedOption(String option) {
Set<Option> recognizedOptions = Option.getJavacToolOptions();
for (Option o : recognizedOptions) {
if (o.matches(option))
return o.hasArg() ? 1 : 0;
}
return -1;
}
}

View File

@@ -0,0 +1,957 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.DocTree;
import com.sun.source.tree.CatchTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Scope;
import com.sun.source.tree.Tree;
import com.sun.source.util.DocSourcePositions;
import com.sun.source.util.DocTreePath;
import com.sun.source.util.DocTreeScanner;
import com.sun.source.util.DocTrees;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ArrayType;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.code.Type.ErrorType;
import com.sun.tools.javac.code.Type.UnionClassType;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.code.Types.TypeRelation;
import com.sun.tools.javac.comp.Attr;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.comp.MemberEnter;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.DCTree;
import com.sun.tools.javac.tree.DCTree.DCBlockTag;
import com.sun.tools.javac.tree.DCTree.DCDocComment;
import com.sun.tools.javac.tree.DCTree.DCEndPosTree;
import com.sun.tools.javac.tree.DCTree.DCErroneous;
import com.sun.tools.javac.tree.DCTree.DCIdentifier;
import com.sun.tools.javac.tree.DCTree.DCParam;
import com.sun.tools.javac.tree.DCTree.DCReference;
import com.sun.tools.javac.tree.DCTree.DCText;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeCopier;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Pair;
import com.sun.tools.javac.util.Position;
import static com.sun.tools.javac.code.TypeTag.*;
/**
* Provides an implementation of Trees.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Peter von der Ah&eacute;
*/
public class JavacTrees extends DocTrees {
// in a world of a single context per compilation, these would all be final
private Resolve resolve;
private Enter enter;
private Log log;
private MemberEnter memberEnter;
private Attr attr;
private TreeMaker treeMaker;
private JavacElements elements;
private JavacTaskImpl javacTaskImpl;
private Names names;
private Types types;
// called reflectively from Trees.instance(CompilationTask task)
public static JavacTrees instance(JavaCompiler.CompilationTask task) {
if (!(task instanceof BasicJavacTask))
throw new IllegalArgumentException();
return instance(((BasicJavacTask)task).getContext());
}
// called reflectively from Trees.instance(ProcessingEnvironment env)
public static JavacTrees instance(ProcessingEnvironment env) {
if (!(env instanceof JavacProcessingEnvironment))
throw new IllegalArgumentException();
return instance(((JavacProcessingEnvironment)env).getContext());
}
public static JavacTrees instance(Context context) {
JavacTrees instance = context.get(JavacTrees.class);
if (instance == null)
instance = new JavacTrees(context);
return instance;
}
protected JavacTrees(Context context) {
context.put(JavacTrees.class, this);
init(context);
}
public void updateContext(Context context) {
init(context);
}
private void init(Context context) {
attr = Attr.instance(context);
enter = Enter.instance(context);
elements = JavacElements.instance(context);
log = Log.instance(context);
resolve = Resolve.instance(context);
treeMaker = TreeMaker.instance(context);
memberEnter = MemberEnter.instance(context);
names = Names.instance(context);
types = Types.instance(context);
JavacTask t = context.get(JavacTask.class);
if (t instanceof JavacTaskImpl)
javacTaskImpl = (JavacTaskImpl) t;
}
public DocSourcePositions getSourcePositions() {
return new DocSourcePositions() {
public long getStartPosition(CompilationUnitTree file, Tree tree) {
return TreeInfo.getStartPos((JCTree) tree);
}
public long getEndPosition(CompilationUnitTree file, Tree tree) {
EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions;
return TreeInfo.getEndPos((JCTree) tree, endPosTable);
}
public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
return ((DCTree) tree).getSourcePosition((DCDocComment) comment);
}
@SuppressWarnings("fallthrough")
public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
DCDocComment dcComment = (DCDocComment) comment;
if (tree instanceof DCEndPosTree) {
int endPos = ((DCEndPosTree) tree).getEndPos(dcComment);
if (endPos != Position.NOPOS) {
return endPos;
}
}
int correction = 0;
switch (tree.getKind()) {
case TEXT:
DCText text = (DCText) tree;
return dcComment.comment.getSourcePos(text.pos + text.text.length());
case ERRONEOUS:
DCErroneous err = (DCErroneous) tree;
return dcComment.comment.getSourcePos(err.pos + err.body.length());
case IDENTIFIER:
DCIdentifier ident = (DCIdentifier) tree;
return dcComment.comment.getSourcePos(ident.pos + (ident.name != names.error ? ident.name.length() : 0));
case PARAM:
DCParam param = (DCParam) tree;
if (param.isTypeParameter && param.getDescription().isEmpty()) {
correction = 1;
}
case AUTHOR: case DEPRECATED: case RETURN: case SEE:
case SERIAL: case SERIAL_DATA: case SERIAL_FIELD: case SINCE:
case THROWS: case UNKNOWN_BLOCK_TAG: case VERSION: {
DocTree last = getLastChild(tree);
if (last != null) {
return getEndPosition(file, comment, last) + correction;
}
DCBlockTag block = (DCBlockTag) tree;
return dcComment.comment.getSourcePos(block.pos + block.getTagName().length() + 1);
}
default:
DocTree last = getLastChild(tree);
if (last != null) {
return getEndPosition(file, comment, last);
}
break;
}
return Position.NOPOS;
}
};
}
private DocTree getLastChild(DocTree tree) {
final DocTree[] last = new DocTree[] {null};
tree.accept(new DocTreeScanner<Void, Void>() {
@Override public Void scan(DocTree node, Void p) {
if (node != null) last[0] = node;
return null;
}
}, null);
return last[0];
}
public JCClassDecl getTree(TypeElement element) {
return (JCClassDecl) getTree((Element) element);
}
public JCMethodDecl getTree(ExecutableElement method) {
return (JCMethodDecl) getTree((Element) method);
}
public JCTree getTree(Element element) {
Symbol symbol = (Symbol) element;
TypeSymbol enclosing = symbol.enclClass();
Env<AttrContext> env = enter.getEnv(enclosing);
if (env == null)
return null;
JCClassDecl classNode = env.enclClass;
if (classNode != null) {
if (TreeInfo.symbolFor(classNode) == element)
return classNode;
for (JCTree node : classNode.getMembers())
if (TreeInfo.symbolFor(node) == element)
return node;
}
return null;
}
public JCTree getTree(Element e, AnnotationMirror a) {
return getTree(e, a, null);
}
public JCTree getTree(Element e, AnnotationMirror a, AnnotationValue v) {
Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
if (treeTopLevel == null)
return null;
return treeTopLevel.fst;
}
public TreePath getPath(CompilationUnitTree unit, Tree node) {
return TreePath.getPath(unit, node);
}
public TreePath getPath(Element e) {
return getPath(e, null, null);
}
public TreePath getPath(Element e, AnnotationMirror a) {
return getPath(e, a, null);
}
public TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v) {
final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
if (treeTopLevel == null)
return null;
return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
}
public Symbol getElement(TreePath path) {
JCTree tree = (JCTree) path.getLeaf();
Symbol sym = TreeInfo.symbolFor(tree);
if (sym == null) {
if (TreeInfo.isDeclaration(tree)) {
for (TreePath p = path; p != null; p = p.getParentPath()) {
JCTree t = (JCTree) p.getLeaf();
if (t.hasTag(JCTree.Tag.CLASSDEF)) {
JCClassDecl ct = (JCClassDecl) t;
if (ct.sym != null) {
if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
attr.attribClass(ct.pos(), ct.sym);
sym = TreeInfo.symbolFor(tree);
}
break;
}
}
}
}
}
return sym;
}
@Override
public Element getElement(DocTreePath path) {
DocTree forTree = path.getLeaf();
if (forTree instanceof DCReference)
return attributeDocReference(path.getTreePath(), ((DCReference) forTree));
if (forTree instanceof DCIdentifier) {
if (path.getParentPath().getLeaf() instanceof DCParam) {
return attributeParamIdentifier(path.getTreePath(), (DCParam) path.getParentPath().getLeaf());
}
}
return null;
}
private Symbol attributeDocReference(TreePath path, DCReference ref) {
Env<AttrContext> env = getAttrContext(path);
Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
new Log.DeferredDiagnosticHandler(log);
try {
final TypeSymbol tsym;
final Name memberName;
if (ref.qualifierExpression == null) {
tsym = env.enclClass.sym;
memberName = ref.memberName;
} else {
// See if the qualifierExpression is a type or package name.
// javac does not provide the exact method required, so
// we first check if qualifierExpression identifies a type,
// and if not, then we check to see if it identifies a package.
Type t = attr.attribType(ref.qualifierExpression, env);
if (t.isErroneous()) {
if (ref.memberName == null) {
// Attr/Resolve assume packages exist and create symbols as needed
// so use getPackageElement to restrict search to existing packages
PackageSymbol pck = elements.getPackageElement(ref.qualifierExpression.toString());
if (pck != null) {
return pck;
} else if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
// fixup: allow "identifier" instead of "#identifier"
// for compatibility with javadoc
tsym = env.enclClass.sym;
memberName = ((JCIdent) ref.qualifierExpression).name;
} else
return null;
} else {
return null;
}
} else {
tsym = t.tsym;
memberName = ref.memberName;
}
}
if (memberName == null)
return tsym;
final List<Type> paramTypes;
if (ref.paramTypes == null)
paramTypes = null;
else {
ListBuffer<Type> lb = new ListBuffer<Type>();
for (List<JCTree> l = ref.paramTypes; l.nonEmpty(); l = l.tail) {
JCTree tree = l.head;
Type t = attr.attribType(tree, env);
lb.add(t);
}
paramTypes = lb.toList();
}
ClassSymbol sym = (ClassSymbol) types.cvarUpperBound(tsym.type).tsym;
Symbol msym = (memberName == sym.name)
? findConstructor(sym, paramTypes)
: findMethod(sym, memberName, paramTypes);
if (paramTypes != null) {
// explicit (possibly empty) arg list given, so cannot be a field
return msym;
}
VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName);
// prefer a field over a method with no parameters
if (vsym != null &&
(msym == null ||
types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) {
return vsym;
} else {
return msym;
}
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
} finally {
log.popDiagnosticHandler(deferredDiagnosticHandler);
}
}
private Symbol attributeParamIdentifier(TreePath path, DCParam ptag) {
Symbol javadocSymbol = getElement(path);
if (javadocSymbol == null)
return null;
ElementKind kind = javadocSymbol.getKind();
List<? extends Symbol> params = List.nil();
if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
MethodSymbol ee = (MethodSymbol) javadocSymbol;
params = ptag.isTypeParameter()
? ee.getTypeParameters()
: ee.getParameters();
} else if (kind.isClass() || kind.isInterface()) {
ClassSymbol te = (ClassSymbol) javadocSymbol;
params = te.getTypeParameters();
}
for (Symbol param : params) {
if (param.getSimpleName() == ptag.getName().getName()) {
return param;
}
}
return null;
}
/** @see com.sun.tools.javadoc.ClassDocImpl#findField */
private VarSymbol findField(ClassSymbol tsym, Name fieldName) {
return searchField(tsym, fieldName, new HashSet<ClassSymbol>());
}
/** @see com.sun.tools.javadoc.ClassDocImpl#searchField */
private VarSymbol searchField(ClassSymbol tsym, Name fieldName, Set<ClassSymbol> searched) {
if (searched.contains(tsym)) {
return null;
}
searched.add(tsym);
for (com.sun.tools.javac.code.Scope.Entry e = tsym.members().lookup(fieldName);
e.scope != null; e = e.next()) {
if (e.sym.kind == Kinds.VAR) {
return (VarSymbol)e.sym;
}
}
//### If we found a VarSymbol above, but which did not pass
//### the modifier filter, we should return failure here!
ClassSymbol encl = tsym.owner.enclClass();
if (encl != null) {
VarSymbol vsym = searchField(encl, fieldName, searched);
if (vsym != null) {
return vsym;
}
}
// search superclass
Type superclass = tsym.getSuperclass();
if (superclass.tsym != null) {
VarSymbol vsym = searchField((ClassSymbol) superclass.tsym, fieldName, searched);
if (vsym != null) {
return vsym;
}
}
// search interfaces
List<Type> intfs = tsym.getInterfaces();
for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
Type intf = l.head;
if (intf.isErroneous()) continue;
VarSymbol vsym = searchField((ClassSymbol) intf.tsym, fieldName, searched);
if (vsym != null) {
return vsym;
}
}
return null;
}
/** @see com.sun.tools.javadoc.ClassDocImpl#findConstructor */
MethodSymbol findConstructor(ClassSymbol tsym, List<Type> paramTypes) {
for (com.sun.tools.javac.code.Scope.Entry e = tsym.members().lookup(names.init);
e.scope != null; e = e.next()) {
if (e.sym.kind == Kinds.MTH) {
if (hasParameterTypes((MethodSymbol) e.sym, paramTypes)) {
return (MethodSymbol) e.sym;
}
}
}
return null;
}
/** @see com.sun.tools.javadoc.ClassDocImpl#findMethod */
private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List<Type> paramTypes) {
return searchMethod(tsym, methodName, paramTypes, new HashSet<ClassSymbol>());
}
/** @see com.sun.tools.javadoc.ClassDocImpl#searchMethod */
private MethodSymbol searchMethod(ClassSymbol tsym, Name methodName,
List<Type> paramTypes, Set<ClassSymbol> searched) {
//### Note that this search is not necessarily what the compiler would do!
// do not match constructors
if (methodName == names.init)
return null;
if (searched.contains(tsym))
return null;
searched.add(tsym);
// search current class
com.sun.tools.javac.code.Scope.Entry e = tsym.members().lookup(methodName);
//### Using modifier filter here isn't really correct,
//### but emulates the old behavior. Instead, we should
//### apply the normal rules of visibility and inheritance.
if (paramTypes == null) {
// If no parameters specified, we are allowed to return
// any method with a matching name. In practice, the old
// code returned the first method, which is now the last!
// In order to provide textually identical results, we
// attempt to emulate the old behavior.
MethodSymbol lastFound = null;
for (; e.scope != null; e = e.next()) {
if (e.sym.kind == Kinds.MTH) {
if (e.sym.name == methodName) {
lastFound = (MethodSymbol)e.sym;
}
}
}
if (lastFound != null) {
return lastFound;
}
} else {
for (; e.scope != null; e = e.next()) {
if (e.sym != null &&
e.sym.kind == Kinds.MTH) {
if (hasParameterTypes((MethodSymbol) e.sym, paramTypes)) {
return (MethodSymbol) e.sym;
}
}
}
}
//### If we found a MethodSymbol above, but which did not pass
//### the modifier filter, we should return failure here!
// search superclass
Type superclass = tsym.getSuperclass();
if (superclass.tsym != null) {
MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, searched);
if (msym != null) {
return msym;
}
}
// search interfaces
List<Type> intfs = tsym.getInterfaces();
for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
Type intf = l.head;
if (intf.isErroneous()) continue;
MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, searched);
if (msym != null) {
return msym;
}
}
// search enclosing class
ClassSymbol encl = tsym.owner.enclClass();
if (encl != null) {
MethodSymbol msym = searchMethod(encl, methodName, paramTypes, searched);
if (msym != null) {
return msym;
}
}
return null;
}
/** @see com.sun.tools.javadoc.ClassDocImpl */
private boolean hasParameterTypes(MethodSymbol method, List<Type> paramTypes) {
if (paramTypes == null)
return true;
if (method.params().size() != paramTypes.size())
return false;
List<Type> methodParamTypes = types.erasureRecursive(method.asType()).getParameterTypes();
return (Type.isErroneous(paramTypes))
? fuzzyMatch(paramTypes, methodParamTypes)
: types.isSameTypes(paramTypes, methodParamTypes);
}
boolean fuzzyMatch(List<Type> paramTypes, List<Type> methodParamTypes) {
List<Type> l1 = paramTypes;
List<Type> l2 = methodParamTypes;
while (l1.nonEmpty()) {
if (!fuzzyMatch(l1.head, l2.head))
return false;
l1 = l1.tail;
l2 = l2.tail;
}
return true;
}
boolean fuzzyMatch(Type paramType, Type methodParamType) {
Boolean b = fuzzyMatcher.visit(paramType, methodParamType);
return (b == Boolean.TRUE);
}
TypeRelation fuzzyMatcher = new TypeRelation() {
@Override
public Boolean visitType(Type t, Type s) {
if (t == s)
return true;
if (s.isPartial())
return visit(s, t);
switch (t.getTag()) {
case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
return t.hasTag(s.getTag());
default:
throw new AssertionError("fuzzyMatcher " + t.getTag());
}
}
@Override
public Boolean visitArrayType(ArrayType t, Type s) {
if (t == s)
return true;
if (s.isPartial())
return visit(s, t);
return s.hasTag(ARRAY)
&& visit(t.elemtype, types.elemtype(s));
}
@Override
public Boolean visitClassType(ClassType t, Type s) {
if (t == s)
return true;
if (s.isPartial())
return visit(s, t);
return t.tsym == s.tsym;
}
@Override
public Boolean visitErrorType(ErrorType t, Type s) {
return s.hasTag(CLASS)
&& t.tsym.name == ((ClassType) s).tsym.name;
}
};
public TypeMirror getTypeMirror(TreePath path) {
Tree t = path.getLeaf();
return ((JCTree)t).type;
}
public JavacScope getScope(TreePath path) {
return new JavacScope(getAttrContext(path));
}
public String getDocComment(TreePath path) {
CompilationUnitTree t = path.getCompilationUnit();
Tree leaf = path.getLeaf();
if (t instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) {
JCCompilationUnit cu = (JCCompilationUnit) t;
if (cu.docComments != null) {
return cu.docComments.getCommentText((JCTree) leaf);
}
}
return null;
}
public DocCommentTree getDocCommentTree(TreePath path) {
CompilationUnitTree t = path.getCompilationUnit();
Tree leaf = path.getLeaf();
if (t instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) {
JCCompilationUnit cu = (JCCompilationUnit) t;
if (cu.docComments != null) {
return cu.docComments.getCommentTree((JCTree) leaf);
}
}
return null;
}
public boolean isAccessible(Scope scope, TypeElement type) {
if (scope instanceof JavacScope && type instanceof ClassSymbol) {
Env<AttrContext> env = ((JavacScope) scope).env;
return resolve.isAccessible(env, (ClassSymbol)type, true);
} else
return false;
}
public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
if (scope instanceof JavacScope
&& member instanceof Symbol
&& type instanceof com.sun.tools.javac.code.Type) {
Env<AttrContext> env = ((JavacScope) scope).env;
return resolve.isAccessible(env, (com.sun.tools.javac.code.Type)type, (Symbol)member, true);
} else
return false;
}
private Env<AttrContext> getAttrContext(TreePath path) {
if (!(path.getLeaf() instanceof JCTree)) // implicit null-check
throw new IllegalArgumentException();
// if we're being invoked from a Tree API client via parse/enter/analyze,
// we need to make sure all the classes have been entered;
// if we're being invoked from JSR 199 or JSR 269, then the classes
// will already have been entered.
if (javacTaskImpl != null) {
try {
javacTaskImpl.enter(null);
} catch (IOException e) {
throw new Error("unexpected error while entering symbols: " + e);
}
}
JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit();
Copier copier = createCopier(treeMaker.forToplevel(unit));
Env<AttrContext> env = null;
JCMethodDecl method = null;
JCVariableDecl field = null;
List<Tree> l = List.nil();
TreePath p = path;
while (p != null) {
l = l.prepend(p.getLeaf());
p = p.getParentPath();
}
for ( ; l.nonEmpty(); l = l.tail) {
Tree tree = l.head;
switch (tree.getKind()) {
case COMPILATION_UNIT:
// System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
env = enter.getTopLevelEnv((JCCompilationUnit)tree);
break;
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case INTERFACE:
// System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
env = enter.getClassEnv(((JCClassDecl)tree).sym);
break;
case METHOD:
// System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
method = (JCMethodDecl)tree;
env = memberEnter.getMethodEnv(method, env);
break;
case VARIABLE:
// System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
field = (JCVariableDecl)tree;
break;
case BLOCK: {
// System.err.println("BLOCK: ");
if (method != null) {
try {
Assert.check(method.body == tree);
method.body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
env = attribStatToTree(method.body, env, copier.leafCopy);
} finally {
method.body = (JCBlock) tree;
}
} else {
JCBlock body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
env = attribStatToTree(body, env, copier.leafCopy);
}
return env;
}
default:
// System.err.println("DEFAULT: " + tree.getKind());
if (field != null && field.getInitializer() == tree) {
env = memberEnter.getInitEnv(field, env);
JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf());
env = attribExprToTree(expr, env, copier.leafCopy);
return env;
}
}
}
return (field != null) ? memberEnter.getInitEnv(field, env) : env;
}
private Env<AttrContext> attribStatToTree(JCTree stat, Env<AttrContext>env, JCTree tree) {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try {
return attr.attribStatToTree(stat, env, tree);
} finally {
log.useSource(prev);
}
}
private Env<AttrContext> attribExprToTree(JCExpression expr, Env<AttrContext>env, JCTree tree) {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try {
return attr.attribExprToTree(expr, env, tree);
} finally {
log.useSource(prev);
}
}
/**
* Makes a copy of a tree, noting the value resulting from copying a particular leaf.
**/
protected static class Copier extends TreeCopier<JCTree> {
JCTree leafCopy = null;
protected Copier(TreeMaker M) {
super(M);
}
@Override
public <T extends JCTree> T copy(T t, JCTree leaf) {
T t2 = super.copy(t, leaf);
if (t == leaf)
leafCopy = t2;
return t2;
}
}
protected Copier createCopier(TreeMaker maker) {
return new Copier(maker);
}
/**
* Gets the original type from the ErrorType object.
* @param errorType The errorType for which we want to get the original type.
* @returns TypeMirror corresponding to the original type, replaced by the ErrorType.
* noType (type.tag == NONE) is returned if there is no original type.
*/
public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) {
return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType();
}
return com.sun.tools.javac.code.Type.noType;
}
/**
* Prints a message of the specified kind at the location of the
* tree within the provided compilation unit
*
* @param kind the kind of message
* @param msg the message, or an empty string if none
* @param t the tree to use as a position hint
* @param root the compilation unit that contains tree
*/
public void printMessage(Diagnostic.Kind kind, CharSequence msg,
com.sun.source.tree.Tree t,
com.sun.source.tree.CompilationUnitTree root) {
printMessage(kind, msg, ((JCTree) t).pos(), root);
}
public void printMessage(Diagnostic.Kind kind, CharSequence msg,
com.sun.source.doctree.DocTree t,
com.sun.source.doctree.DocCommentTree c,
com.sun.source.tree.CompilationUnitTree root) {
printMessage(kind, msg, ((DCTree) t).pos((DCDocComment) c), root);
}
private void printMessage(Diagnostic.Kind kind, CharSequence msg,
JCDiagnostic.DiagnosticPosition pos,
com.sun.source.tree.CompilationUnitTree root) {
JavaFileObject oldSource = null;
JavaFileObject newSource = null;
newSource = root.getSourceFile();
if (newSource == null) {
pos = null;
} else {
oldSource = log.useSource(newSource);
}
try {
switch (kind) {
case ERROR:
boolean prev = log.multipleErrors;
try {
log.error(pos, "proc.messager", msg.toString());
} finally {
log.multipleErrors = prev;
}
break;
case WARNING:
log.warning(pos, "proc.messager", msg.toString());
break;
case MANDATORY_WARNING:
log.mandatoryWarning(pos, "proc.messager", msg.toString());
break;
default:
log.note(pos, "proc.messager", msg.toString());
}
} finally {
if (oldSource != null)
log.useSource(oldSource);
}
}
@Override
public TypeMirror getLub(CatchTree tree) {
JCCatch ct = (JCCatch) tree;
JCVariableDecl v = ct.param;
if (v.type != null && v.type.getKind() == TypeKind.UNION) {
UnionClassType ut = (UnionClassType) v.type;
return ut.getLub();
} else {
return v.type;
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.util.Locale;
import java.util.MissingResourceException;
/**
* This interface defines the minimum requirements in order to provide support
* for localized formatted strings.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*
* @author Maurizio Cimadamore
*/
public interface Messages {
/**
* Add a new resource bundle to the list that is searched for localized messages.
* @param bundleName the name to identify the resource bundle of localized messages.
* @throws MissingResourceException if the given resource is not found
*/
void add(String bundleName) throws MissingResourceException;
/**
* Get a localized formatted string.
* @param l locale in which the text is to be localized
* @param key locale-independent message key
* @param args misc message arguments
* @return a localized formatted string
*/
String getLocalizedString(Locale l, String key, Object... args);
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.util.Arrays;
import java.util.Collection;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.util.Context;
/**
* TODO.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class MultiTaskListener implements TaskListener {
/** The context key for the MultiTaskListener. */
public static final Context.Key<MultiTaskListener> taskListenerKey =
new Context.Key<MultiTaskListener>();
/** Get the MultiTaskListener instance for this context. */
public static MultiTaskListener instance(Context context) {
MultiTaskListener instance = context.get(taskListenerKey);
if (instance == null)
instance = new MultiTaskListener(context);
return instance;
}
protected MultiTaskListener(Context context) {
context.put(taskListenerKey, this);
ccw = ClientCodeWrapper.instance(context);
}
/**
* The current set of registered listeners.
* This is a mutable reference to an immutable array.
*/
TaskListener[] listeners = { };
ClientCodeWrapper ccw;
public Collection<TaskListener> getTaskListeners() {
return Arrays.asList(listeners);
}
public boolean isEmpty() {
return (listeners.length == 0);
}
public void add(TaskListener listener) {
for (TaskListener l: listeners) {
if (ccw.unwrap(l) == listener)
throw new IllegalStateException();
}
listeners = Arrays.copyOf(listeners, listeners.length + 1);
listeners[listeners.length - 1] = ccw.wrap(listener);
}
public void remove(TaskListener listener) {
for (int i = 0; i < listeners.length; i++) {
if (ccw.unwrap(listeners[i]) == listener) {
TaskListener[] newListeners = new TaskListener[listeners.length - 1];
System.arraycopy(listeners, 0, newListeners, 0, i);
System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i);
listeners = newListeners;
break;
}
}
}
@Override
public void started(TaskEvent e) {
// guard against listeners being updated by a listener
TaskListener[] ll = this.listeners;
for (TaskListener l: ll)
l.started(e);
}
@Override
public void finished(TaskEvent e) {
// guard against listeners being updated by a listener
TaskListener[] ll = this.listeners;
for (TaskListener l: ll)
l.finished(e);
}
@Override
public String toString() {
return Arrays.toString(listeners);
}
}

View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.api;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.tools.*;
import javax.tools.JavaFileObject.Kind;
/**
* Wraps all calls to a given file manager. Subclasses of this class
* might override some of these methods and might also provide
* additional fields and methods.
*
* <p>This class might be moved to {@link javax.tools} in a future
* release.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @param <M> the type of file manager wrapped to by this object
*
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public class WrappingJavaFileManager<M extends JavaFileManager> extends ForwardingJavaFileManager<M> {
/**
* Creates a new instance of WrappingJavaFileManager.
* @param fileManager file manager to be wrapped
*/
protected WrappingJavaFileManager(M fileManager) {
super(fileManager);
}
/**
* This implementation returns the given file object. Subclasses
* may override this behavior.
*
* @param fileObject a file object
*/
protected FileObject wrap(FileObject fileObject) {
return fileObject;
}
/**
* This implementation forwards to {@link #wrap(FileObject)}.
* Subclasses may override this behavior.
*
* @param fileObject a file object
* @throws ClassCastException if the file object returned from the
* forwarded call is not a subtype of {@linkplain JavaFileObject}
*/
protected JavaFileObject wrap(JavaFileObject fileObject) {
return (JavaFileObject)wrap((FileObject)fileObject);
}
/**
* This implementation returns the given file object. Subclasses
* may override this behavior.
*
* @param fileObject a file object
*/
protected FileObject unwrap(FileObject fileObject) {
return fileObject;
}
/**
* This implementation forwards to {@link #unwrap(FileObject)}.
* Subclasses may override this behavior.
*
* @param fileObject a file object
* @throws ClassCastException if the file object returned from the
* forwarded call is not a subtype of {@linkplain JavaFileObject}
*/
protected JavaFileObject unwrap(JavaFileObject fileObject) {
return (JavaFileObject)unwrap((FileObject)fileObject);
}
/**
* This implementation maps the given list of file objects by
* calling wrap on each. Subclasses may override this behavior.
*
* @param fileObjects a list of file objects
* @return the mapping
*/
protected Iterable<JavaFileObject> wrap(Iterable<JavaFileObject> fileObjects) {
List<JavaFileObject> mapped = new ArrayList<JavaFileObject>();
for (JavaFileObject fileObject : fileObjects)
mapped.add(wrap(fileObject));
return Collections.unmodifiableList(mapped);
}
/**
* This implementation returns the given URI. Subclasses may
* override this behavior.
*
* @param uri a URI
*/
protected URI unwrap(URI uri) {
return uri;
}
/**
* @throws IllegalStateException {@inheritDoc}
*/
public Iterable<JavaFileObject> list(Location location,
String packageName,
Set<Kind> kinds,
boolean recurse)
throws IOException
{
return wrap(super.list(location, packageName, kinds, recurse));
}
/**
* @throws IllegalStateException {@inheritDoc}
*/
public String inferBinaryName(Location location, JavaFileObject file) {
return super.inferBinaryName(location, unwrap(file));
}
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws UnsupportedOperationException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*/
public JavaFileObject getJavaFileForInput(Location location,
String className,
Kind kind)
throws IOException
{
return wrap(super.getJavaFileForInput(location, className, kind));
}
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws UnsupportedOperationException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*/
public JavaFileObject getJavaFileForOutput(Location location,
String className,
Kind kind,
FileObject sibling)
throws IOException
{
return wrap(super.getJavaFileForOutput(location, className, kind, unwrap(sibling)));
}
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*/
public FileObject getFileForInput(Location location,
String packageName,
String relativeName)
throws IOException
{
return wrap(super.getFileForInput(location, packageName, relativeName));
}
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*/
public FileObject getFileForOutput(Location location,
String packageName,
String relativeName,
FileObject sibling)
throws IOException
{
return wrap(super.getFileForOutput(location,
packageName,
relativeName,
unwrap(sibling)));
}
}