[Gradle] Format java source code

This commit is contained in:
Akash Yadav
2022-08-14 08:42:34 +05:30
parent 6e8c708381
commit 6ec5c6d3cf
107 changed files with 1872 additions and 1765 deletions
@@ -479,7 +479,7 @@ public class DesignerActivity extends StudioActivity
TransitionManager.beginDelayedTransition(
mBinding.navigation,
new TransitionSet().addTransition(new Slide(Gravity.END)).addTransition(new Fade()));
this.mBinding.groupItems.getAdapter().notifyDataSetChanged();
}
@@ -39,7 +39,9 @@ public class SimpleIconTextAdapter extends IconTextAdapter<IconTextListItem> {
@Override
public int getItemCount() {
return items.size();
} @NonNull
}
@NonNull
@Override
public IconTextListItem getItemAt(int index) {
return items.get(index);
@@ -55,6 +57,4 @@ public class SimpleIconTextAdapter extends IconTextAdapter<IconTextListItem> {
public String getItemText(int index) {
return getItemAt(index).getText();
}
}
@@ -22,6 +22,7 @@ public class WizardTemplateAdapter extends RecyclerView.Adapter<WizardTemplateAd
private final List<ProjectTemplate> mItems = new ArrayList<>();
private OnItemClickListener mListener;
public WizardTemplateAdapter() {}
public void setOnItemClickListener(OnItemClickListener listener) {
@@ -76,7 +76,7 @@ public class FileTreeViewHolder extends TreeNode.BaseNodeViewHolder<File> {
} else {
chevronIcon = R.drawable.ic_chevron_right;
}
TransitionManager.beginDelayedTransition(binding.getRoot(), new ChangeImageTransform());
binding.filetreeChevron.setImageResource(chevronIcon);
binding
@@ -74,7 +74,7 @@ public abstract class BaseValueEditorFragment extends Fragment {
if (child != null) {
scrollView.addView(child);
}
return scrollView;
}
@@ -40,7 +40,7 @@ import java.util.Arrays;
public class FlagEditor extends FixedValueEditor {
private static final ILogger LOG = ILogger.newInstance("FlagEditor");
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -153,7 +153,7 @@ public class EditorPreferences extends BasePreferenceFragment
visiblePasswordFlag.setKey(FLAG_PASSWORD);
visiblePasswordFlag.setTitle(getString(R.string.idepref_visiblePassword_title));
visiblePasswordFlag.setSummary(getString(R.string.idepref_visiblePassword_summary));
useIcu.setIcon(R.drawable.ic_expand_selection);
useIcu.setKey(USE_ICU);
useIcu.setTitle(getString(R.string.idepref_useIcu_title));
@@ -18,7 +18,6 @@ package com.itsaky.androidide.language;
import androidx.annotation.NonNull;
import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.lsp.api.ILanguageServer;
import com.itsaky.androidide.models.prefs.EditorPreferencesKt;
@@ -33,19 +32,19 @@ import io.github.rosemoe.sora.lang.format.Formatter;
public abstract class IDELanguage implements Language {
private Formatter formatter;
@Override
public boolean useTab() {
return false;
}
@NonNull
@Override
public Formatter getFormatter() {
if (formatter != null) {
return formatter;
}
return formatter = new LSPFormatter(getLanguageServer());
}
@@ -68,8 +68,7 @@ public class KotlinLanguage extends IDELanguage {
@NonNull CharPosition position,
@NonNull CompletionPublisher publisher,
@NonNull Bundle extraArguments)
throws CompletionCancelledException {
}
throws CompletionCancelledException {}
@Override
public int getIndentAdvance(@NonNull ContentReference content, int line, int column) {
@@ -33,8 +33,9 @@ public class Symbols {
}
if (file.isFile()) {
if (file.getName().endsWith(".java") || file.getName().endsWith(".gradle") || file.getName().endsWith(".kt"))
return javaSymbols();
if (file.getName().endsWith(".java")
|| file.getName().endsWith(".gradle")
|| file.getName().endsWith(".kt")) return javaSymbols();
if (file.getName().endsWith(".xml")) return xmlSymbols();
}
@@ -36,99 +36,89 @@ public class WizardViewModel extends AndroidViewModel {
public void createTemplatesList() {
TaskExecutor.executeAsync(this::createTemplates);
}
private Void createTemplates() {
List<ProjectTemplate> mTemplates = new ArrayList<>();
ProjectTemplate
empty =
new ProjectTemplate()
.setId(0)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_empty)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_empty)
.setImageId(R.drawable.template_empty_activity),
basic =
new ProjectTemplate()
.setId(1)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_basic)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_basic)
.setImageId(R.drawable.template_basic_activity),
drawer =
new ProjectTemplate()
.setId(2)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(),
R.string.template_navigation_drawer)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_navigation_drawer)
.setImageId(R.drawable.template_blank_activity_drawer),
bottomTabs =
new ProjectTemplate()
.setId(3)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(),
R.string.template_navigation_tabs)
.setImageId(R.drawable.template_bottom_navigation_activity),
tabs =
new ProjectTemplate()
.setId(4)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_tabs)
.setImageId(R.drawable.template_blank_activity_tabs),
fragmentViewModel =
new ProjectTemplate()
.setId(5)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(),
R.string.template_fragment_and_viewmodel)
.setImageId(R.drawable.template_empty_activity),
cppWizard =
new ProjectTemplate()
.setId(6)
.setSupportJava(true)
.setSupportKotlin(true)
.setIsCpp(true)
.setName(getApplication().getApplicationContext(), R.string.template_cpp)
.setImageId(R.drawable.template_cpp_configure),
compose =
new ProjectTemplate()
.setId(7)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_compose)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_compose)
.setImageId(R.drawable.template_compose_empty_activity),
libgdx =
new ProjectTemplate()
.setId(8)
.setSupportJava(true)
.setName(
getApplication().getApplicationContext(), R.string.template_libgdx)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_libgdx)
.setImageId(R.drawable.template_game_activity);
empty =
new ProjectTemplate()
.setId(0)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_empty)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_empty)
.setImageId(R.drawable.template_empty_activity),
basic =
new ProjectTemplate()
.setId(1)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_basic)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_basic)
.setImageId(R.drawable.template_basic_activity),
drawer =
new ProjectTemplate()
.setId(2)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_navigation_drawer)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_navigation_drawer)
.setImageId(R.drawable.template_blank_activity_drawer),
bottomTabs =
new ProjectTemplate()
.setId(3)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_navigation_tabs)
.setImageId(R.drawable.template_bottom_navigation_activity),
tabs =
new ProjectTemplate()
.setId(4)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_tabs)
.setImageId(R.drawable.template_blank_activity_tabs),
fragmentViewModel =
new ProjectTemplate()
.setId(5)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(),
R.string.template_fragment_and_viewmodel)
.setImageId(R.drawable.template_empty_activity),
cppWizard =
new ProjectTemplate()
.setId(6)
.setSupportJava(true)
.setSupportKotlin(true)
.setIsCpp(true)
.setName(getApplication().getApplicationContext(), R.string.template_cpp)
.setImageId(R.drawable.template_cpp_configure),
compose =
new ProjectTemplate()
.setId(7)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_compose)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_compose)
.setImageId(R.drawable.template_compose_empty_activity),
libgdx =
new ProjectTemplate()
.setId(8)
.setSupportJava(true)
.setName(getApplication().getApplicationContext(), R.string.template_libgdx)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_libgdx)
.setImageId(R.drawable.template_game_activity);
mTemplates.add(empty);
mTemplates.add(basic);
mTemplates.add(drawer);
@@ -138,7 +128,7 @@ public class WizardViewModel extends AndroidViewModel {
mTemplates.add(cppWizard);
mTemplates.add(compose);
mTemplates.add(libgdx);
mProjectTemplatesList.postValue(mTemplates);
mLoadingState.postValue(false);
@@ -343,7 +343,7 @@ public class CodeEditorView extends FrameLayout {
binding.editor.setTextSize(textSize);
}
private void onUseIcuPrefChanged() {
binding.editor.getProps().useICULibToSelectWords = getUseIcu();
}
@@ -384,7 +384,7 @@ public class CodeEditorView extends FrameLayout {
break;
}
}
public boolean save() {
final var file = getFile();
if (file == null) {
@@ -189,6 +189,7 @@ public abstract class Doc {
private final RealOrImaginary realOrImaginary;
private final Indent plusIndentCommentsBefore;
private final Optional<Indent> breakAndIndentTrailingComment;
private Token(
Input.Token token,
RealOrImaginary realOrImaginary,
@@ -29,6 +29,7 @@ public abstract class InputOutput {
private static final DiscreteDomain<Integer> INTEGERS = DiscreteDomain.integers();
/** The {@link Range}s of the tokens or comments lying on each line, in any part. */
protected final List<Range<Integer>> ranges = new ArrayList<>();
private ImmutableList<String> lines = ImmutableList.of();
/**
@@ -69,6 +69,7 @@ public class ImportOrderer {
.thenComparing(Import::isThirdParty, trueFirst())
.thenComparing(Import::isJava, trueFirst())
.thenComparing(Import::imported);
private final String text;
private final ImmutableList<Tok> toks;
private final String lineSeparator;
@@ -31,6 +31,7 @@ public class JavaFormatterOptions {
private final Style style;
private final boolean formatJavadoc;
private JavaFormatterOptions(Style style, boolean formatJavadoc) {
this.style = style;
this.formatJavadoc = formatJavadoc;
@@ -71,6 +71,7 @@ public final class JavaInput extends Input {
*/
/** Map from Tok index to the associated Token. */
private final Token[] kToToken;
private int kN; // The number of numbered toks (tokens or comments), excluding the EOF.
private JCCompilationUnit unit;
@@ -44,6 +44,7 @@ public final class Main {
private final PrintWriter outWriter;
private final PrintWriter errWriter;
private final InputStream inStream;
public Main(PrintWriter outWriter, PrintWriter errWriter, InputStream inStream) {
this.outWriter = outWriter;
this.errWriter = errWriter;
@@ -31,6 +31,7 @@ public final class Replacement {
private final Range<Integer> replaceRange;
private final String replacementString;
private Replacement(Range<Integer> replaceRange, String replacementString) {
this.replaceRange = checkNotNull(replaceRange, "Null replaceRange");
this.replacementString = checkNotNull(replacementString, "Null replacementString");
@@ -118,6 +118,7 @@ final class JavadocLexer {
private final NestingCounter codeDepth = new NestingCounter();
private final NestingCounter tableDepth = new NestingCounter();
private boolean somethingSinceNewline;
private JavadocLexer(CharStream input) {
this.input = checkNotNull(input);
}
@@ -22,6 +22,7 @@ package com.google.googlejavaformat.java.javadoc;
final class Token {
private final Type type;
private final String value;
Token(Type type, String value) {
this.type = type;
this.value = value;
@@ -52,6 +52,7 @@ public class NBMemberEnter extends MemberEnter {
private final CancelService cancelService;
private final JavacTrees trees;
private final boolean backgroundScan;
public NBMemberEnter(Context context, boolean backgroundScan) {
super(context);
cancelService = CancelService.instance(context);
@@ -55,6 +55,7 @@ public class NBNames {
public static void preRegister(Context context) {
context.put(nbNamesKey, (Context.Factory<NBNames>) NBNames::new);
}
protected NBNames(Context context) {
Names n = Names.instance(context);
@@ -50,6 +50,7 @@ public class NBTreeMaker extends TreeMaker {
private final Names names;
private final Types types;
private final Symtab syms;
protected NBTreeMaker(JCCompilationUnit toplevel, Names names, Types types, Symtab syms) {
super(toplevel, names, types, syms);
this.names = names;
@@ -41,6 +41,7 @@ public class CollectionTypeAdapter<E> extends TypeAdapter<Collection<E>> {
private final Type elementType;
private final TypeAdapter<E> elementTypeAdapter;
private final Supplier<Collection<E>> constructor;
public CollectionTypeAdapter(
Gson gson,
Type elementType,
@@ -42,9 +42,11 @@ public class EitherTypeAdapter<L, R> extends TypeAdapter<Either<L, R>> {
protected final EitherTypeArgument<R> right;
protected final Predicate<JsonElement> leftChecker;
protected final Predicate<JsonElement> rightChecker;
public EitherTypeAdapter(Gson gson, TypeToken<Either<L, R>> typeToken) {
this(gson, typeToken, null, null);
}
public EitherTypeAdapter(
Gson gson,
TypeToken<Either<L, R>> typeToken,
@@ -31,6 +31,7 @@ public class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
private final Map<String, T> nameToConstant = new HashMap<>();
private final Map<Integer, T> valueToConstant = new HashMap<>();
private final Map<T, Integer> constantToValue = new HashMap<>();
EnumTypeAdapter(Class<T> classOfT) throws IllegalAccessException {
try {
Field valueField = classOfT.getDeclaredField(VALUE_FIELD_NAME);
@@ -26,6 +26,7 @@ public class JsonElementTypeAdapter extends TypeAdapter<Object> {
private final Gson gson;
private final TypeAdapter<JsonElement> adapter;
public JsonElementTypeAdapter(Gson gson) {
this.gson = gson;
this.adapter = gson.getAdapter(JsonElement.class);
@@ -57,6 +57,7 @@ public class MessageTypeAdapter extends TypeAdapter<Message> {
private static Type[] EMPTY_TYPE_ARRAY = {};
private final MessageJsonHandler handler;
private final Gson gson;
public MessageTypeAdapter(MessageJsonHandler handler, Gson gson) {
this.handler = handler;
this.gson = gson;
@@ -105,6 +105,7 @@ public final class SdkConstants {
public static final String FN_ANDROID_MANIFEST_XML = "AndroidManifest.xml"; // $NON-NLS-1$
/** pre-dex jar filename. i.e. "classes.jar" */
public static final String TOOLS_NS_NAME = "tools";
public static final String FN_CLASSES_JAR = "classes.jar";
/** Dex filename inside the APK. i.e. "classes.dex" */
public static final String FN_APK_CLASSES_DEX = "classes.dex"; // $NON-NLS-1$
@@ -537,6 +538,7 @@ public final class SdkConstants {
*/
public static final String CLASS_MOCK_VIEW =
"com.android.layoutlib.bridge.MockView"; //$NON-NLS-1$
public static final String CLASS_LAYOUT_INFLATER = "android.view.LayoutInflater"; // $NON-NLS-1$
/* Android Design Support Class Constants */
public static final String CLASS_COORDINATOR_LAYOUT =
@@ -606,6 +608,7 @@ public final class SdkConstants {
public static final String ANDROID_NS_NAME = "android"; // $NON-NLS-1$
/** The default prefix used for the {@link #ANDROID_URI} name space including the colon */
public static final String ANDROID_NS_NAME_PREFIX = "android:"; // $NON-NLS-1$
public static final int ANDROID_NS_NAME_PREFIX_LEN = ANDROID_NS_NAME_PREFIX.length();
/** The default prefix used for the app */
public static final String APP_PREFIX = "app"; // $NON-NLS-1$
@@ -619,6 +622,7 @@ public final class SdkConstants {
public static final String LT_ENTITY = "&lt;"; // $NON-NLS-1$
/** The entity for the greater than character */
public static final String GT_ENTITY = "&gt;"; // $NON-NLS-1$
public static final String NEWLINE_ENTITY = "&#xA;";
/** Namespace prefix used for all resources */
public static final String URI_PREFIX = "http://schemas.android.com/apk/res/"; // $NON-NLS-1$
@@ -1017,6 +1021,7 @@ public final class SdkConstants {
public static final String FN_MANIFEST_CLASS = FN_MANIFEST_BASE + DOT_JAVA;
/** BuildConfig java class filename, i.e. "BuildConfig.java" */
public static final String FN_BUILD_CONFIG = FN_BUILD_CONFIG_BASE + DOT_JAVA;
public static final String DRAWABLE_FOLDER = "drawable"; // $NON-NLS-1$
public static final String DRAWABLE_XHDPI = "drawable-xhdpi"; // $NON-NLS-1$
public static final String DRAWABLE_XXHDPI = "drawable-xxhdpi"; // $NON-NLS-1$
@@ -1170,6 +1175,7 @@ public final class SdkConstants {
public static final String FQCN_RELATIVE_LAYOUT = "android.widget.RelativeLayout"; // $NON-NLS-1$
/** The fully qualified class name of a RelativeLayout view */
public static final String FQCN_GRID_LAYOUT = "android.widget.GridLayout"; // $NON-NLS-1$
public static final String FQCN_GRID_LAYOUT_V7 =
"android.support.v7.widget.GridLayout"; //$NON-NLS-1$
/** The fully qualified class name of a FrameLayout view */
@@ -1208,11 +1214,13 @@ public final class SdkConstants {
public static final String FQCN_RADIO_GROUP = "android.widgets.RadioGroup"; // $NON-NLS-1$
/** The fully qualified class name of a Space */
public static final String FQCN_SPACE = "android.widget.Space"; // $NON-NLS-1$
public static final String FQCN_SPACE_V7 = "android.support.v7.widget.Space"; // $NON-NLS-1$
/** The fully qualified class name of a TextView view */
public static final String FQCN_TEXT_VIEW = "android.widget.TextView"; // $NON-NLS-1$
/** The fully qualified class name of an ImageView view */
public static final String FQCN_IMAGE_VIEW = "android.widget.ImageView"; // $NON-NLS-1$
public static final String ATTR_SRC = "src"; // $NON-NLS-1$
public static final String ATTR_GRAVITY = "gravity"; // $NON-NLS-1$
public static final String ATTR_WEIGHT_SUM = "weightSum"; // $NON-NLS-1$
@@ -84,6 +84,7 @@ public enum XmlAttributeSortOrder {
return attr1.getName().compareTo(attr2.getName());
}
};
public final String key;
XmlAttributeSortOrder(String key) {
@@ -50,6 +50,7 @@ import java.util.List;
public class SdkUtils {
/** Prefix in comments which mark the source locations for merge results */
public static final String FILENAME_PREFIX = "From: ";
public static final List<String> IMAGE_EXTENSIONS =
ImmutableList.of(DOT_PNG, DOT_9PNG, DOT_GIF, DOT_JPEG, DOT_JPG, DOT_BMP, DOT_WEBP);
/** For use by {@link #getLineSeparator()} */
@@ -161,12 +161,14 @@ public class ColorPickerView extends LinearLayout {
@Override
public void afterTextChanged(Editable s) {}
} /**
}
/**
* Set the color value of this picker to the given hex color code.
*
* @param hexCode The hex color code.
* @see #setColor(int)
*/
public void setColor(final String hexCode) {
setColor(parseColor(hexCode));
}
@@ -185,12 +187,14 @@ public class ColorPickerView extends LinearLayout {
* @param hexCode The hex color code of the color.
*/
void onPick(int color, String hexCode);
} /**
}
/**
* Set the color value for this color picker. this will in turn update value of the sliders and
* the color preview.
*
* @param color The new color value.
*/
public void setColor(int color) {
this.alpha = alpha(color);
this.red = red(color);
@@ -219,8 +223,4 @@ public class ColorPickerView extends LinearLayout {
private void updatePreview() {
this.binding.colorPreview.setBackgroundColor(getColor());
}
}
@@ -115,12 +115,14 @@ public class CharSequenceInputStream extends InputStream {
public CharSequenceInputStream(
final CharSequence cs, final String charset, final int bufferSize) {
this(cs, toCharset(charset), bufferSize);
} /**
}
/**
* Return an estimate of the number of bytes remaining in the byte stream.
*
* @return the count of bytes that can be read without blocking (or returning EOF).
* @throws IOException if an error occurs (probably not possible).
*/
@Override
public int available() throws IOException {
// The cached entries are in bbuf; since encoding always creates at least one byte
@@ -132,7 +134,9 @@ public class CharSequenceInputStream extends InputStream {
static Charset toCharset(final String charsetName) throws UnsupportedCharsetException {
return charsetName == null ? Charset.defaultCharset() : Charset.forName(charsetName);
} @Override
}
@Override
public void close() throws IOException {
// noop
}
@@ -144,11 +148,13 @@ public class CharSequenceInputStream extends InputStream {
*/
CharsetEncoder getCharsetEncoder() {
return charsetEncoder;
} /**
}
/**
* Fills the byte output buffer from the input char buffer.
*
* @throws CharacterCodingException an error encoding data.
*/
private void fillBuffer() throws CharacterCodingException {
this.bBuf.compact();
final CoderResult result = this.charsetEncoder.encode(this.cBuf, this.bBuf, true);
@@ -158,8 +164,6 @@ public class CharSequenceInputStream extends InputStream {
this.bBuf.flip();
}
/**
* {@inheritDoc}
*
@@ -288,8 +292,4 @@ public class CharSequenceInputStream extends InputStream {
}
return skipped;
}
}
@@ -58,6 +58,7 @@ public class CharSequenceReader extends Reader implements Serializable {
* @since 2.7
*/
private final Integer end;
private int idx;
private int mark;
@@ -132,7 +133,9 @@ public class CharSequenceReader extends Reader implements Serializable {
public String toString() {
final CharSequence subSequence = charSequence.subSequence(start(), end());
return subSequence.toString();
} /** Close resets the file back to the start and removes any marked position. */
}
/** Close resets the file back to the start and removes any marked position. */
@Override
public void close() {
idx = start;
@@ -147,11 +150,13 @@ public class CharSequenceReader extends Reader implements Serializable {
*/
private int start() {
return Math.min(charSequence.length(), start);
} /**
}
/**
* Returns the index in the character sequence to end reading at, taking into account its length.
*
* @return The end index in the character sequence (exclusive).
*/
private int end() {
/*
* end == null for de-serialized instances that were serialized before start and end were added.
@@ -281,8 +286,4 @@ public class CharSequenceReader extends Reader implements Serializable {
idx = dest;
return count;
}
}
@@ -36,19 +36,19 @@ import org.json.JSONObject;
*
* <p>Examples: {@code # Empty: []
*
* <p><p><p><p><p><p><p># Single row: [[ESC, TAB, CTRL, ALT, {key: '-', popup: '|'}, DOWN, UP]]
* <p><p><p><p><p><p><p><p># Single row: [[ESC, TAB, CTRL, ALT, {key: '-', popup: '|'}, DOWN, UP]]
*
* <p><p><p><p><p><p><p># 2 row: [['ESC','/',{key: '-', popup: '|'},'HOME','UP','END','PGUP'],
* <p><p><p><p><p><p><p><p># 2 row: [['ESC','/',{key: '-', popup: '|'},'HOME','UP','END','PGUP'],
* ['TAB','CTRL','ALT','LEFT','DOWN','RIGHT','PGDN']]
*
* <p><p><p><p><p><p><p># Advance: [[ {key: ESC, popup: {macro: "CTRL f d", display: "tmux exit"}},
* {key: CTRL, popup: {macro: "CTRL f BKSP", display: "tmux ←"}}, {key: ALT, popup: {macro: "CTRL f
* TAB", display: "tmux →"}}, {key: TAB, popup: {macro: "ALT a", display: A-a}}, {key: LEFT, popup:
* HOME}, {key: DOWN, popup: PGDN}, {key: UP, popup: PGUP}, {key: RIGHT, popup: END}, {macro: "ALT
* j", display: A-j, popup: {macro: "ALT g", display: A-g}}, {key: KEYBOARD, popup: {macro: "CTRL
* d", display: exit}} ]]
* <p><p><p><p><p><p><p><p># Advance: [[ {key: ESC, popup: {macro: "CTRL f d", display: "tmux
* exit"}}, {key: CTRL, popup: {macro: "CTRL f BKSP", display: "tmux ←"}}, {key: ALT, popup: {macro:
* "CTRL f TAB", display: "tmux →"}}, {key: TAB, popup: {macro: "ALT a", display: A-a}}, {key: LEFT,
* popup: HOME}, {key: DOWN, popup: PGDN}, {key: UP, popup: PGUP}, {key: RIGHT, popup: END}, {macro:
* "ALT j", display: A-j, popup: {macro: "ALT g", display: A-g}}, {key: KEYBOARD, popup: {macro:
* "CTRL d", display: exit}} ]]
*
* <p><p><p><p><p><p><p>}
* <p><p><p><p><p><p><p><p>}
*
* <p>Aliases are also allowed for the keys that you can pass as {@code extraKeyAliasMap}. Check
* {@link VirtualKeysConstants#CONTROL_CHARS_ALIASES}.
@@ -151,10 +151,12 @@ public final class VirtualKeysView extends GridLayout {
* and a swipe up action is done on an extra key.
*/
private PopupWindow mPopupWindow;
private ScheduledExecutorService mScheduledExecutor;
private Handler mHandler;
private SpecialButtonsLongHoldRunnable mSpecialButtonsLongHoldRunnable;
private int mLongPressCount;
public VirtualKeysView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -15,6 +15,7 @@ public final class TerminalBuffer {
private int mActiveTranscriptRows = 0;
/** The index in the circular buffer where the visible screen starts. */
private int mScreenFirstRow = 0;
TerminalRow[] mLines;
/** The length of {@link #mLines}. */
int mTotalRows;
@@ -33,6 +33,7 @@ public final class TerminalEmulator {
public static final int MOUSE_LEFT_BUTTON = 0;
/** Mouse moving while having left mouse button pressed. */
public static final int MOUSE_LEFT_BUTTON_MOVED = 32;
public static final int MOUSE_WHEELUP_BUTTON = 64;
public static final int MOUSE_WHEELDOWN_BUTTON = 65;
/**
@@ -42,6 +43,7 @@ public final class TerminalEmulator {
public static final int UNICODE_REPLACEMENT_CHAR = 0xFFFD;
/** The number of terminal transcript rows that can be scrolled back to. */
public static final int TERMINAL_TRANSCRIPT_ROWS_MIN = 100;
public static final int TERMINAL_TRANSCRIPT_ROWS_MAX = 50000;
public static final int DEFAULT_TERMINAL_TRANSCRIPT_ROWS = 2000;
public static final int TERMINAL_CURSOR_STYLE_BLOCK = 0;
@@ -101,6 +103,7 @@ public final class TerminalEmulator {
private static final int MAX_OSC_STRING_LENGTH = 8192;
/** DECSET 1 - application cursor keys. */
private static final int DECSET_BIT_APPLICATION_CURSOR_KEYS = 1;
private static final int DECSET_BIT_REVERSE_VIDEO = 1 << 1;
/**
* http://www.vt100.net/docs/vt510-rm/DECOM: "When DECOM is set, the home cursor position is at
@@ -121,6 +124,7 @@ public final class TerminalEmulator {
private static final int DECSET_BIT_AUTOWRAP = 1 << 3;
/** DECSET 25 - if the cursor should be enabled, {@link #isCursorEnabled()}. */
private static final int DECSET_BIT_CURSOR_ENABLED = 1 << 4;
private static final int DECSET_BIT_APPLICATION_KEYPAD = 1 << 5;
/** DECSET 1000 - if to report mouse press&release events. */
private static final int DECSET_BIT_MOUSE_TRACKING_PRESS_RELEASE = 1 << 6;
@@ -138,6 +142,7 @@ public final class TerminalEmulator {
/* The supported terminal cursor styles. */
/** Not really DECSET bit... - http://www.vt100.net/docs/vt510-rm/DECSACE */
private static final int DECSET_BIT_RECTANGULAR_CHANGEATTRIBUTE = 1 << 12;
private static final String LOG_TAG = "TerminalEmulator";
public final TerminalColors mColors = new TerminalColors();
private final Stack<String> mTitleStack = new Stack<>();
@@ -152,6 +157,7 @@ public final class TerminalEmulator {
private final int[] mArgs = new int[MAX_ESCAPE_PARAMETERS];
/** Holds OSC and device control arguments, which can be strings. */
private final StringBuilder mOSCOrDeviceControlArgs = new StringBuilder();
private final SavedScreenState mSavedStateMain = new SavedScreenState();
private final SavedScreenState mSavedStateAlt = new SavedScreenState();
private final byte[] mUtf8InputBuffer = new byte[4];
@@ -165,6 +171,7 @@ public final class TerminalEmulator {
final TerminalBuffer mAltBuffer;
/** The number of character rows and columns in the terminal screen. */
public int mRows, mColumns;
private String mTitle;
/** The cursor position. Between (0,0) and (mRows-1, mColumns-1). */
private int mCursorRow, mCursorCol;
@@ -227,6 +234,7 @@ public final class TerminalEmulator {
* selection up along with the scrolling text.
*/
private int mScrollCounter = 0;
private byte mUtf8ToFollow, mUtf8Index;
private int mLastEmittedCodePoint = -1;
TerminalSessionClient mClient;
@@ -38,6 +38,7 @@ public final class TerminalSession extends TerminalOutput {
public final String mHandle = UUID.randomUUID().toString();
/** Buffer to write translate code points into utf8 before writing to mTerminalToProcessIOQueue */
private final byte[] mUtf8InputBuffer = new byte[5];
private final String mShellPath;
private final String mCwd;
private final String[] mArgs;
@@ -53,6 +54,7 @@ public final class TerminalSession extends TerminalOutput {
* which forwards by writing to the {@link #mTerminalFileDescriptor}.
*/
final ByteQueue mTerminalToProcessIOQueue = new ByteQueue(4096);
final Handler mMainThreadHandler = new Handler(Looper.getMainLooper(), new MainThreadHandler());
/** Set by the application for user identification of session, not by terminal. */
public String mSessionName;
@@ -61,6 +63,7 @@ public final class TerminalSession extends TerminalOutput {
* calling {@link JNI#createSubprocess(String, String, String[], String[], int[], int, int)}.
*/
private int mTerminalFileDescriptor;
TerminalEmulator mEmulator;
/** Callback which gets notified when a session finishes or changes title. */
TerminalSessionClient mClient;
@@ -26,6 +26,7 @@ public final class TextStyle {
public static final int CHARACTER_ATTRIBUTE_PROTECTED = 1 << 7;
/** Dim colors. Also known as faint or half intensity. */
public static final int CHARACTER_ATTRIBUTE_DIM = 1 << 8;
public static final int COLOR_INDEX_FOREGROUND = 256;
public static final int COLOR_INDEX_BACKGROUND = 257;
public static final int COLOR_INDEX_CURSOR = 258;
@@ -12,6 +12,7 @@ final class GestureAndScaleRecognizer {
private final ScaleGestureDetector mScaleDetector;
final Listener mListener;
boolean isAfterLongPress;
public GestureAndScaleRecognizer(Context context, Listener listener) {
mListener = listener;
@@ -23,6 +23,7 @@ public final class TerminalRenderer {
* The {@link Paint#ascent()}. See http://www.fampennings.nl/maarten/android/08numgrid/font.png
*/
private final int mFontAscent;
private final float[] asciiMeasures = new float[127];
final int mTextSize;
final Typeface mTypeface;
@@ -41,6 +41,7 @@ public final class TerminalView extends View {
private static final String LOG_TAG = "TerminalView";
/** Log terminal view key and IME events. */
private static boolean TERMINAL_VIEW_KEY_LOGGING_ENABLED = false;
private final boolean mAccessibilityEnabled;
final GestureAndScaleRecognizer mGestureRecognizer;
final Scroller mScroller;
@@ -48,6 +49,7 @@ public final class TerminalView extends View {
public TerminalSession mTermSession;
/** Our terminal emulator whose session is {@link #mTermSession}. */
public TerminalEmulator mEmulator;
public TerminalRenderer mRenderer;
public TerminalViewClient mClient;
private TextSelectionCursorController mTextSelectionCursorController;
@@ -61,6 +63,7 @@ public final class TerminalView extends View {
}
}
};
private Handler mTerminalCursorBlinkerHandler;
private TerminalCursorBlinkerRunnable mTerminalCursorBlinkerRunnable;
private int mTerminalCursorBlinkerRate;
@@ -71,6 +74,7 @@ public final class TerminalView extends View {
private long mMouseStartDownTime = -1;
/** The top row of text to display. Ranges from -activeTranscriptRows to 0. */
int mTopRow;
int[] mDefaultSelectors = new int[] {-1, -1, -1, -1};
float mScaleFactor = 1.f;
/** What was left in from scrolling movement. */
@@ -22,60 +22,60 @@ import android.os.SystemClock;
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
} finally {
handlerActive = rescheduled;
}
}
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
}
@@ -1,11 +1,9 @@
package org.greenrobot.eventbus.android;
/**
* Used via reflection in the Java library by {@link AndroidDependenciesDetector}.
*/
/** Used via reflection in the Java library by {@link AndroidDependenciesDetector}. */
public class AndroidComponentsImpl extends AndroidComponents {
public AndroidComponentsImpl() {
super(new AndroidLogger("EventBus"), new DefaultAndroidMainThreadSupport());
}
public AndroidComponentsImpl() {
super(new AndroidLogger("EventBus"), new DefaultAndroidMainThreadSupport());
}
}
@@ -22,39 +22,39 @@ import java.util.logging.Level;
public class AndroidLogger implements Logger {
private final String tag;
private final String tag;
public AndroidLogger(String tag) {
this.tag = tag;
}
public AndroidLogger(String tag) {
this.tag = tag;
}
public void log(Level level, String msg) {
if (level != Level.OFF) {
Log.println(mapLevel(level), tag, msg);
}
public void log(Level level, String msg) {
if (level != Level.OFF) {
Log.println(mapLevel(level), tag, msg);
}
}
public void log(Level level, String msg, Throwable th) {
if (level != Level.OFF) {
// That's how Log does it internally
Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th));
}
public void log(Level level, String msg, Throwable th) {
if (level != Level.OFF) {
// That's how Log does it internally
Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th));
}
}
private int mapLevel(Level level) {
int value = level.intValue();
if (value < 800) { // below INFO
if (value < 500) { // below FINE
return Log.VERBOSE;
} else {
return Log.DEBUG;
}
} else if (value < 900) { // below WARNING
return Log.INFO;
} else if (value < 1000) { // below ERROR
return Log.WARN;
} else {
return Log.ERROR;
}
private int mapLevel(Level level) {
int value = level.intValue();
if (value < 800) { // below INFO
if (value < 500) { // below FINE
return Log.VERBOSE;
} else {
return Log.DEBUG;
}
} else if (value < 900) { // below WARNING
return Log.INFO;
} else if (value < 1000) { // below ERROR
return Log.WARN;
} else {
return Log.ERROR;
}
}
}
@@ -8,13 +8,13 @@ import org.greenrobot.eventbus.Poster;
public class DefaultAndroidMainThreadSupport implements MainThreadSupport {
@Override
public boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
@Override
public boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);
}
}
@@ -15,35 +15,33 @@
*/
package org.greenrobot.eventbus;
/**
* Posts events in background.
*
*
* @author Markus
*/
class AsyncPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
private final PendingPostQueue queue;
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
eventBus.invokeSubscriber(pendingPost);
}
}
@@ -24,51 +24,52 @@ import java.util.logging.Level;
*/
final class BackgroundPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!executorRunning) {
executorRunning = true;
eventBus.getExecutorService().execute(this);
}
}
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!executorRunning) {
executorRunning = true;
eventBus.getExecutorService().execute(this);
@Override
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
eventBus
.getLogger()
.log(Level.WARNING, Thread.currentThread().getName() + " was interrupted", e);
}
} finally {
executorRunning = false;
}
@Override
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interrupted", e);
}
} finally {
executorRunning = false;
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -23,171 +23,171 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
* Create a new builder using {@link EventBus#builder()}.
* Creates EventBus instances with custom parameters and also allows to install a custom default
* EventBus instance. Create a new builder using {@link EventBus#builder()}.
*/
@SuppressWarnings("unused")
public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
private static final ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
List<Class<?>> skipMethodVerificationForClasses;
List<SubscriberInfoIndex> subscriberInfoIndexes;
Logger logger;
MainThreadSupport mainThreadSupport;
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
List<Class<?>> skipMethodVerificationForClasses;
List<SubscriberInfoIndex> subscriberInfoIndexes;
Logger logger;
MainThreadSupport mainThreadSupport;
EventBusBuilder() {
EventBusBuilder() {}
/** Default: true */
public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
this.logSubscriberExceptions = logSubscriberExceptions;
return this;
}
/** Default: true */
public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
this.logNoSubscriberMessages = logNoSubscriberMessages;
return this;
}
/** Default: true */
public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
return this;
}
/** Default: true */
public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
this.sendNoSubscriberEvent = sendNoSubscriberEvent;
return this;
}
/**
* Fails if an subscriber throws an exception (default: false).
*
* <p>Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way,
* you won't miss exceptions during development.
*/
public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
this.throwSubscriberException = throwSubscriberException;
return this;
}
/**
* By default, EventBus considers the event class hierarchy (subscribers to super classes will be
* notified). Switching this feature off will improve posting of events. For simple event classes
* extending Object directly, we measured a speed up of 20% for event posting. For more complex
* event hierarchies, the speed up should be greater than 20%.
*
* <p>However, keep in mind that event posting usually consumes just a small proportion of CPU
* time inside an app, unless it is posting at high rates, e.g. hundreds/thousands of events per
* second.
*/
public EventBusBuilder eventInheritance(boolean eventInheritance) {
this.eventInheritance = eventInheritance;
return this;
}
/**
* Provide a custom thread pool to EventBus used for async and background event delivery. This is
* an advanced setting to that can break things: ensure the given ExecutorService won't get stuck
* to avoid undefined behavior.
*/
public EventBusBuilder executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
/**
* Method name verification is done for methods starting with onEvent to avoid typos; using this
* method you can exclude subscriber classes from this check. Also disables checks for method
* modifiers (public, not static nor abstract).
*/
public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
if (skipMethodVerificationForClasses == null) {
skipMethodVerificationForClasses = new ArrayList<>();
}
skipMethodVerificationForClasses.add(clazz);
return this;
}
/** Default: true */
public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
this.logSubscriberExceptions = logSubscriberExceptions;
return this;
/** Forces the use of reflection even if there's a generated index (default: false). */
public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
return this;
}
/** Enables strict method verification (default: false). */
public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
this.strictMethodVerification = strictMethodVerification;
return this;
}
/** Adds an index generated by EventBus' annotation preprocessor. */
public EventBusBuilder addIndex(SubscriberInfoIndex index) {
if (subscriberInfoIndexes == null) {
subscriberInfoIndexes = new ArrayList<>();
}
subscriberInfoIndexes.add(index);
return this;
}
/** Default: true */
public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
this.logNoSubscriberMessages = logNoSubscriberMessages;
return this;
/**
* Set a specific log handler for all EventBus logging.
*
* <p>By default, all logging is via {@code android.util.Log} on Android or System.out on JVM.
*/
public EventBusBuilder logger(Logger logger) {
this.logger = logger;
return this;
}
Logger getLogger() {
if (logger != null) {
return logger;
} else {
return Logger.Default.get();
}
}
/** Default: true */
public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
return this;
MainThreadSupport getMainThreadSupport() {
if (mainThreadSupport != null) {
return mainThreadSupport;
} else if (AndroidComponents.areAvailable()) {
return AndroidComponents.get().defaultMainThreadSupport;
} else {
return null;
}
}
/** Default: true */
public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
this.sendNoSubscriberEvent = sendNoSubscriberEvent;
return this;
}
/**
* Fails if an subscriber throws an exception (default: false).
* <p/>
* Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
* exceptions during development.
*/
public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
this.throwSubscriberException = throwSubscriberException;
return this;
}
/**
* By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
* Switching this feature off will improve posting of events. For simple event classes extending Object directly,
* we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
* greater than 20%.
* <p/>
* However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
* unless it is posting at high rates, e.g. hundreds/thousands of events per second.
*/
public EventBusBuilder eventInheritance(boolean eventInheritance) {
this.eventInheritance = eventInheritance;
return this;
}
/**
* Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
* setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
*/
public EventBusBuilder executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
/**
* Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
* exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
* abstract).
*/
public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
if (skipMethodVerificationForClasses == null) {
skipMethodVerificationForClasses = new ArrayList<>();
}
skipMethodVerificationForClasses.add(clazz);
return this;
}
/** Forces the use of reflection even if there's a generated index (default: false). */
public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
return this;
}
/** Enables strict method verification (default: false). */
public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
this.strictMethodVerification = strictMethodVerification;
return this;
}
/** Adds an index generated by EventBus' annotation preprocessor. */
public EventBusBuilder addIndex(SubscriberInfoIndex index) {
if (subscriberInfoIndexes == null) {
subscriberInfoIndexes = new ArrayList<>();
}
subscriberInfoIndexes.add(index);
return this;
}
/**
* Set a specific log handler for all EventBus logging.
* <p/>
* By default, all logging is via {@code android.util.Log} on Android or System.out on JVM.
*/
public EventBusBuilder logger(Logger logger) {
this.logger = logger;
return this;
}
Logger getLogger() {
if (logger != null) {
return logger;
} else {
return Logger.Default.get();
}
}
MainThreadSupport getMainThreadSupport() {
if (mainThreadSupport != null) {
return mainThreadSupport;
} else if (AndroidComponents.areAvailable()) {
return AndroidComponents.get().defaultMainThreadSupport;
} else {
return null;
}
}
/**
* Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
* done only once before the first usage of the default EventBus.
*
* @throws EventBusException if there's already a default EventBus instance in place
*/
public EventBus installDefaultEventBus() {
synchronized (EventBus.class) {
if (EventBus.defaultInstance != null) {
throw new EventBusException("Default instance already exists." +
" It may be only set once before it's used the first time to ensure consistent behavior.");
}
EventBus.defaultInstance = build();
return EventBus.defaultInstance;
}
}
/** Builds an EventBus based on the current configuration. */
public EventBus build() {
return new EventBus(this);
/**
* Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders'
* values. Must be done only once before the first usage of the default EventBus.
*
* @throws EventBusException if there's already a default EventBus instance in place
*/
public EventBus installDefaultEventBus() {
synchronized (EventBus.class) {
if (EventBus.defaultInstance != null) {
throw new EventBusException(
"Default instance already exists."
+ " It may be only set once before it's used the first time to ensure consistent behavior.");
}
EventBus.defaultInstance = build();
return EventBus.defaultInstance;
}
}
/** Builds an EventBus based on the current configuration. */
public EventBus build() {
return new EventBus(this);
}
}
@@ -17,24 +17,22 @@ package org.greenrobot.eventbus;
/**
* An {@link RuntimeException} thrown in cases something went wrong inside EventBus.
*
*
* @author Markus
*
*/
public class EventBusException extends RuntimeException {
private static final long serialVersionUID = -2912559384646531479L;
private static final long serialVersionUID = -2912559384646531479L;
public EventBusException(String detailMessage) {
super(detailMessage);
}
public EventBusException(String detailMessage) {
super(detailMessage);
}
public EventBusException(Throwable throwable) {
super(throwable);
}
public EventBusException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
public EventBusException(Throwable throwable) {
super(throwable);
}
public EventBusException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}
@@ -20,54 +20,51 @@ import java.util.logging.Level;
public interface Logger {
void log(Level level, String msg);
void log(Level level, String msg);
void log(Level level, String msg, Throwable th);
void log(Level level, String msg, Throwable th);
class JavaLogger implements Logger {
protected final java.util.logging.Logger logger;
public JavaLogger(String tag) {
logger = java.util.logging.Logger.getLogger(tag);
}
@Override
public void log(Level level, String msg) {
// TODO Replace logged method with caller method
logger.log(level, msg);
}
@Override
public void log(Level level, String msg, Throwable th) {
// TODO Replace logged method with caller method
logger.log(level, msg, th);
}
class JavaLogger implements Logger {
protected final java.util.logging.Logger logger;
public JavaLogger(String tag) {
logger = java.util.logging.Logger.getLogger(tag);
}
class SystemOutLogger implements Logger {
@Override
public void log(Level level, String msg) {
System.out.println("[" + level + "] " + msg);
}
@Override
public void log(Level level, String msg, Throwable th) {
System.out.println("[" + level + "] " + msg);
th.printStackTrace(System.out);
}
@Override
public void log(Level level, String msg) {
// TODO Replace logged method with caller method
logger.log(level, msg);
}
class Default {
public static Logger get() {
if (AndroidComponents.areAvailable()) {
return AndroidComponents.get().logger;
}
@Override
public void log(Level level, String msg, Throwable th) {
// TODO Replace logged method with caller method
logger.log(level, msg, th);
}
}
return new SystemOutLogger();
}
class SystemOutLogger implements Logger {
@Override
public void log(Level level, String msg) {
System.out.println("[" + level + "] " + msg);
}
@Override
public void log(Level level, String msg, Throwable th) {
System.out.println("[" + level + "] " + msg);
th.printStackTrace(System.out);
}
}
class Default {
public static Logger get() {
if (AndroidComponents.areAvailable()) {
return AndroidComponents.get().logger;
}
return new SystemOutLogger();
}
}
}
@@ -16,11 +16,12 @@
package org.greenrobot.eventbus;
/**
* Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used.
* Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's
* main thread is used.
*/
public interface MainThreadSupport {
boolean isMainThread();
boolean isMainThread();
Poster createPoster(EventBus eventBus);
Poster createPoster(EventBus eventBus);
}
@@ -17,19 +17,18 @@ package org.greenrobot.eventbus;
/**
* This Event is posted by EventBus when no subscriber is found for a posted event.
*
*
* @author Markus
*/
public final class NoSubscriberEvent {
/** The {@link EventBus} instance to with the original event was posted to. */
public final EventBus eventBus;
/** The {@link EventBus} instance to with the original event was posted to. */
public final EventBus eventBus;
/** The original event that could not be delivered to any subscriber. */
public final Object originalEvent;
public NoSubscriberEvent(EventBus eventBus, Object originalEvent) {
this.eventBus = eventBus;
this.originalEvent = originalEvent;
}
/** The original event that could not be delivered to any subscriber. */
public final Object originalEvent;
public NoSubscriberEvent(EventBus eventBus, Object originalEvent) {
this.eventBus = eventBus;
this.originalEvent = originalEvent;
}
}
@@ -19,41 +19,40 @@ import java.util.ArrayList;
import java.util.List;
final class PendingPost {
private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
private static final List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
Object event;
Subscription subscription;
PendingPost next;
Object event;
Subscription subscription;
PendingPost next;
private PendingPost(Object event, Subscription subscription) {
this.event = event;
this.subscription = subscription;
}
private PendingPost(Object event, Subscription subscription) {
this.event = event;
this.subscription = subscription;
}
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
PendingPost pendingPost = pendingPostPool.remove(size - 1);
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
return pendingPost;
}
}
return new PendingPost(event, subscription);
}
static void releasePendingPost(PendingPost pendingPost) {
pendingPost.event = null;
pendingPost.subscription = null;
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
PendingPost pendingPost = pendingPostPool.remove(size - 1);
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(pendingPost);
}
}
return pendingPost;
}
}
return new PendingPost(event, subscription);
}
}
static void releasePendingPost(PendingPost pendingPost) {
pendingPost.event = null;
pendingPost.subscription = null;
pendingPost.next = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(pendingPost);
}
}
}
}
@@ -17,40 +17,39 @@
package org.greenrobot.eventbus;
final class PendingPostQueue {
private PendingPost head;
private PendingPost tail;
private PendingPost head;
private PendingPost tail;
synchronized void enqueue(PendingPost pendingPost) {
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
if (tail != null) {
tail.next = pendingPost;
tail = pendingPost;
} else if (head == null) {
head = tail = pendingPost;
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
synchronized void enqueue(PendingPost pendingPost) {
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
synchronized PendingPost poll() {
PendingPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
if (tail != null) {
tail.next = pendingPost;
tail = pendingPost;
} else if (head == null) {
head = tail = pendingPost;
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
}
synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait);
}
return poll();
synchronized PendingPost poll() {
PendingPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
}
synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait);
}
return poll();
}
}
@@ -22,11 +22,11 @@ package org.greenrobot.eventbus;
*/
public interface Poster {
/**
* Enqueue an event to be posted for a particular subscription.
*
* @param subscription Subscription which will receive the event.
* @param event Event that will be posted to subscribers.
*/
void enqueue(Subscription subscription, Object event);
/**
* Enqueue an event to be posted for a particular subscription.
*
* @param subscription Subscription which will receive the event.
* @param event Event that will be posted to subscribers.
*/
void enqueue(Subscription subscription, Object event);
}
@@ -16,7 +16,6 @@
package org.greenrobot.eventbus;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -27,18 +26,19 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* If true, delivers the most recent sticky event (posted with
* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/**
* If true, delivers the most recent sticky event (posted with {@link
* EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/** Subscriber priority to influence the order of event delivery.
* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s! */
int priority() default 0;
/**
* Subscriber priority to influence the order of event delivery. Within the same delivery thread
* ({@link ThreadMode}), higher priority subscribers will receive events before others with a
* lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s!
*/
int priority() default 0;
}
@@ -16,29 +16,29 @@
package org.greenrobot.eventbus;
/**
* This Event is posted by EventBus when an exception occurs inside a subscriber's event handling method.
*
* This Event is posted by EventBus when an exception occurs inside a subscriber's event handling
* method.
*
* @author Markus
*/
public final class SubscriberExceptionEvent {
/** The {@link EventBus} instance to with the original event was posted to. */
public final EventBus eventBus;
/** The {@link EventBus} instance to with the original event was posted to. */
public final EventBus eventBus;
/** The Throwable thrown by a subscriber. */
public final Throwable throwable;
/** The Throwable thrown by a subscriber. */
public final Throwable throwable;
/** The original event that could not be delivered to any subscriber. */
public final Object causingEvent;
/** The original event that could not be delivered to any subscriber. */
public final Object causingEvent;
/** The subscriber that threw the Throwable. */
public final Object causingSubscriber;
public SubscriberExceptionEvent(EventBus eventBus, Throwable throwable, Object causingEvent,
Object causingSubscriber) {
this.eventBus = eventBus;
this.throwable = throwable;
this.causingEvent = causingEvent;
this.causingSubscriber = causingSubscriber;
}
/** The subscriber that threw the Throwable. */
public final Object causingSubscriber;
public SubscriberExceptionEvent(
EventBus eventBus, Throwable throwable, Object causingEvent, Object causingSubscriber) {
this.eventBus = eventBus;
this.throwable = throwable;
this.causingEvent = causingEvent;
this.causingSubscriber = causingSubscriber;
}
}
@@ -19,50 +19,52 @@ import java.lang.reflect.Method;
/** Used internally by EventBus and generated subscriber indexes. */
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
/** Used for efficient comparison */
String methodString;
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
/** Used for efficient comparison */
String methodString;
public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
public SubscriberMethod(
Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (other instanceof SubscriberMethod) {
checkMethodString();
SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;
otherSubscriberMethod.checkMethodString();
// Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
return methodString.equals(otherSubscriberMethod.methodString);
} else {
return false;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (other instanceof SubscriberMethod) {
checkMethodString();
SubscriberMethod otherSubscriberMethod = (SubscriberMethod) other;
otherSubscriberMethod.checkMethodString();
// Don't use method.equals because of
// http://code.google.com/p/android/issues/detail?id=7811#c6
return methodString.equals(otherSubscriberMethod.methodString);
} else {
return false;
}
}
private synchronized void checkMethodString() {
if (methodString == null) {
// Method.toString has more overhead, just take relevant parts of the method
StringBuilder builder = new StringBuilder(64);
builder.append(method.getDeclaringClass().getName());
builder.append('#').append(method.getName());
builder.append('(').append(eventType.getName());
methodString = builder.toString();
}
private synchronized void checkMethodString() {
if (methodString == null) {
// Method.toString has more overhead, just take relevant parts of the method
StringBuilder builder = new StringBuilder(64);
builder.append(method.getDeclaringClass().getName());
builder.append('#').append(method.getName());
builder.append('(').append(eventType.getName());
methodString = builder.toString();
}
}
@Override
public int hashCode() {
return method.hashCode();
}
}
@Override
public int hashCode() {
return method.hashCode();
}
}
@@ -27,256 +27,277 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
class SubscriberMethodFinder {
/*
* In newer class files, compilers may add methods. Those are called bridge or synthetic methods.
* EventBus must ignore both. There modifiers are not public but defined in the Java class file format:
* http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1
*/
private static final int BRIDGE = 0x40;
private static final int SYNTHETIC = 0x1000;
/*
* In newer class files, compilers may add methods. Those are called bridge or synthetic methods.
* EventBus must ignore both. There modifiers are not public but defined in the Java class file format:
* http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1
*/
private static final int BRIDGE = 0x40;
private static final int SYNTHETIC = 0x1000;
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
private static final int MODIFIERS_IGNORE =
Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE =
new ConcurrentHashMap<>();
private List<SubscriberInfoIndex> subscriberInfoIndexes;
private final boolean strictMethodVerification;
private final boolean ignoreGeneratedIndex;
private List<SubscriberInfoIndex> subscriberInfoIndexes;
private final boolean strictMethodVerification;
private final boolean ignoreGeneratedIndex;
private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
boolean ignoreGeneratedIndex) {
this.subscriberInfoIndexes = subscriberInfoIndexes;
this.strictMethodVerification = strictMethodVerification;
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
SubscriberMethodFinder(
List<SubscriberInfoIndex> subscriberInfoIndexes,
boolean strictMethodVerification,
boolean ignoreGeneratedIndex) {
this.subscriberInfoIndexes = subscriberInfoIndexes;
this.strictMethodVerification = strictMethodVerification;
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
}
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException(
"Subscriber "
+ subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null
&& findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see
// https://github.com/greenrobot/EventBus/issues/149
try {
methods = findState.clazz.getMethods();
} catch (
LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
String msg = "Could not inspect methods of " + findState.clazz.getName();
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
msg += ". Please consider using EventBus annotation processor to avoid reflection.";
} else {
subscriberMethods = findUsingInfo(subscriberClass);
msg +=
". Please make this class visible to EventBus annotation processor to avoid reflection.";
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
throw new EventBusException(msg, error);
}
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(
new SubscriberMethod(
method,
eventType,
threadMode,
subscribeAnnotation.priority(),
subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(
"@Subscribe method "
+ methodName
+ "must have exactly 1 parameter but has "
+ parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(
methodName
+ " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
static void clearCaches() {
METHOD_CACHE.clear();
}
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
boolean checkAdd(Method method, Class<?> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature
// when required.
// Usually a subscriber doesn't have methods listening to the same event type.
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return subscriberMethods;
return checkAddWithMethodSignature(method, eventType);
}
}
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass();
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
// Skip system classes, this degrades performance.
// Also we might avoid some ClassNotFoundException (see FAQ for background).
if (clazzName.startsWith("java.")
|| clazzName.startsWith("javax.")
|| clazzName.startsWith("android.")
|| clazzName.startsWith("androidx.")) {
clazz = null;
}
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
}
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
try {
methods = findState.clazz.getMethods();
} catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
String msg = "Could not inspect methods of " + findState.clazz.getName();
if (ignoreGeneratedIndex) {
msg += ". Please consider using EventBus annotation processor to avoid reflection.";
} else {
msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
}
throw new EventBusException(msg, error);
}
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
static void clearCaches() {
METHOD_CACHE.clear();
}
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
boolean checkAdd(Method method, Class<?> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
// Usually a subscriber doesn't have methods listening to the same event type.
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass();
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
// Skip system classes, this degrades performance.
// Also we might avoid some ClassNotFoundException (see FAQ for background).
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
clazz = null;
}
}
}
}
}
}
@@ -16,33 +16,34 @@
package org.greenrobot.eventbus;
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
/**
* Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
* {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
*/
volatile boolean active;
final Object subscriber;
final SubscriberMethod subscriberMethod;
/**
* Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by
* queued event delivery {@link EventBus#invokeSubscriber(PendingPost)} to prevent race
* conditions.
*/
volatile boolean active;
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
@Override
public boolean equals(Object other) {
if (other instanceof Subscription) {
Subscription otherSubscription = (Subscription) other;
return subscriber == otherSubscription.subscriber
&& subscriberMethod.equals(otherSubscription.subscriberMethod);
} else {
return false;
}
@Override
public boolean equals(Object other) {
if (other instanceof Subscription) {
Subscription otherSubscription = (Subscription) other;
return subscriber == otherSubscription.subscriber
&& subscriberMethod.equals(otherSubscription.subscriberMethod);
} else {
return false;
}
}
@Override
public int hashCode() {
return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
}
}
@Override
public int hashCode() {
return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
}
}
@@ -16,53 +16,58 @@
package org.greenrobot.eventbus;
/**
* Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.
* EventBus takes care of threading independently of the posting thread.
* Each subscriber method has a thread mode, which determines in which thread the method is to be
* called by EventBus. EventBus takes care of threading independently of the posting thread.
*
* @see EventBus#register(Object)
*/
public enum ThreadMode {
/**
* This is the default. Subscriber will be called directly in the same thread, which is posting the event. Event delivery
* implies the least overhead because it avoids thread switching completely. Thus, this is the recommended mode for
* simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
* using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
*/
POSTING,
/**
* This is the default. Subscriber will be called directly in the same thread, which is posting
* the event. Event delivery implies the least overhead because it avoids thread switching
* completely. Thus, this is the recommended mode for simple tasks that are known to complete in a
* very short time without requiring the main thread. Event handlers using this mode must return
* quickly to avoid blocking the posting thread, which may be the main thread.
*/
POSTING,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
* the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
* is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
* <p>
* If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). If the posting
* thread is the main thread, subscriber methods will be called directly, blocking the posting
* thread. Otherwise the event is queued for delivery (non-blocking). Subscribers using this mode
* must return quickly to avoid blocking the main thread.
*
* <p>If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
* the event will always be queued for delivery. This ensures that the post call is non-blocking.
* <p>
* If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN_ORDERED,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). Different from
* {@link #MAIN}, the event will always be queued for delivery. This ensures that the post call is
* non-blocking.
*
* <p>If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN_ORDERED,
/**
* On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods
* will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
* background thread, that will deliver all its events sequentially. Subscribers using this mode should try to
* return quickly to avoid blocking the background thread.
* <p>
* If not on Android, always uses a background thread.
*/
BACKGROUND,
/**
* On Android, subscriber will be called in a background thread. If posting thread is not the main
* thread, subscriber methods will be called directly in the posting thread. If the posting thread
* is the main thread, EventBus uses a single background thread, that will deliver all its events
* sequentially. Subscribers using this mode should try to return quickly to avoid blocking the
* background thread.
*
* <p>If not on Android, always uses a background thread.
*/
BACKGROUND,
/**
* Subscriber will be called in a separate thread. This is always independent of the posting thread and the
* main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should
* use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
* of long-running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus
* uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
*/
ASYNC
}
/**
* Subscriber will be called in a separate thread. This is always independent of the posting
* thread and the main thread. Posting events never wait for subscriber methods using this mode.
* Subscriber methods should use this mode if their execution might take some time, e.g. for
* network access. Avoid triggering a large number of long-running asynchronous subscriber methods
* at the same time to limit the number of concurrent threads. EventBus uses a thread pool to
* efficiently reuse threads from completed asynchronous subscriber notifications.
*/
ASYNC
}
@@ -5,27 +5,28 @@ import org.greenrobot.eventbus.MainThreadSupport;
public abstract class AndroidComponents {
private static final AndroidComponents implementation;
private static final AndroidComponents implementation;
static {
implementation = AndroidDependenciesDetector.isAndroidSDKAvailable()
static {
implementation =
AndroidDependenciesDetector.isAndroidSDKAvailable()
? AndroidDependenciesDetector.instantiateAndroidComponents()
: null;
}
}
public static boolean areAvailable() {
return implementation != null;
}
public static boolean areAvailable() {
return implementation != null;
}
public static AndroidComponents get() {
return implementation;
}
public static AndroidComponents get() {
return implementation;
}
public final Logger logger;
public final MainThreadSupport defaultMainThreadSupport;
public final Logger logger;
public final MainThreadSupport defaultMainThreadSupport;
public AndroidComponents(Logger logger, MainThreadSupport defaultMainThreadSupport) {
this.logger = logger;
this.defaultMainThreadSupport = defaultMainThreadSupport;
}
public AndroidComponents(Logger logger, MainThreadSupport defaultMainThreadSupport) {
this.logger = logger;
this.defaultMainThreadSupport = defaultMainThreadSupport;
}
}
@@ -6,43 +6,42 @@ import java.lang.reflect.Method;
@SuppressWarnings("TryWithIdenticalCatches")
public class AndroidDependenciesDetector {
public static boolean isAndroidSDKAvailable() {
public static boolean isAndroidSDKAvailable() {
try {
Class<?> looperClass = Class.forName("android.os.Looper");
Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper");
Object mainLooper = getMainLooper.invoke(null);
return mainLooper != null;
}
catch (ClassNotFoundException ignored) {}
catch (NoSuchMethodException ignored) {}
catch (IllegalAccessException ignored) {}
catch (InvocationTargetException ignored) {}
return false;
try {
Class<?> looperClass = Class.forName("android.os.Looper");
Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper");
Object mainLooper = getMainLooper.invoke(null);
return mainLooper != null;
} catch (ClassNotFoundException ignored) {
} catch (NoSuchMethodException ignored) {
} catch (IllegalAccessException ignored) {
} catch (InvocationTargetException ignored) {
}
private static final String ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME = "org.greenrobot.eventbus.android.AndroidComponentsImpl";
return false;
}
public static boolean areAndroidComponentsAvailable() {
private static final String ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME =
"org.greenrobot.eventbus.android.AndroidComponentsImpl";
try {
Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
return true;
}
catch (ClassNotFoundException ex) {
return false;
}
public static boolean areAndroidComponentsAvailable() {
try {
Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
return true;
} catch (ClassNotFoundException ex) {
return false;
}
}
public static AndroidComponents instantiateAndroidComponents() {
public static AndroidComponents instantiateAndroidComponents() {
try {
Class<?> impl = Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
return (AndroidComponents) impl.getConstructor().newInstance();
}
catch (Throwable ex) {
return null;
}
try {
Class<?> impl = Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
return (AndroidComponents) impl.getConstructor().newInstance();
} catch (Throwable ex) {
return null;
}
}
}
@@ -23,58 +23,63 @@ import java.lang.reflect.Method;
/** Base class for generated subscriber meta info classes created by annotation processing. */
public abstract class AbstractSubscriberInfo implements SubscriberInfo {
private final Class subscriberClass;
private final Class<? extends SubscriberInfo> superSubscriberInfoClass;
private final boolean shouldCheckSuperclass;
private final Class subscriberClass;
private final Class<? extends SubscriberInfo> superSubscriberInfoClass;
private final boolean shouldCheckSuperclass;
protected AbstractSubscriberInfo(Class subscriberClass, Class<? extends SubscriberInfo> superSubscriberInfoClass,
boolean shouldCheckSuperclass) {
this.subscriberClass = subscriberClass;
this.superSubscriberInfoClass = superSubscriberInfoClass;
this.shouldCheckSuperclass = shouldCheckSuperclass;
protected AbstractSubscriberInfo(
Class subscriberClass,
Class<? extends SubscriberInfo> superSubscriberInfoClass,
boolean shouldCheckSuperclass) {
this.subscriberClass = subscriberClass;
this.superSubscriberInfoClass = superSubscriberInfoClass;
this.shouldCheckSuperclass = shouldCheckSuperclass;
}
@Override
public Class getSubscriberClass() {
return subscriberClass;
}
@Override
public SubscriberInfo getSuperSubscriberInfo() {
if (superSubscriberInfoClass == null) {
return null;
}
@Override
public Class getSubscriberClass() {
return subscriberClass;
try {
return superSubscriberInfoClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
public SubscriberInfo getSuperSubscriberInfo() {
if(superSubscriberInfoClass == null) {
return null;
}
try {
return superSubscriberInfoClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
@Override
public boolean shouldCheckSuperclass() {
return shouldCheckSuperclass;
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType) {
return createSubscriberMethod(methodName, eventType, ThreadMode.POSTING, 0, false);
}
protected SubscriberMethod createSubscriberMethod(
String methodName, Class<?> eventType, ThreadMode threadMode) {
return createSubscriberMethod(methodName, eventType, threadMode, 0, false);
}
protected SubscriberMethod createSubscriberMethod(
String methodName, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
try {
Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
} catch (NoSuchMethodException e) {
throw new EventBusException(
"Could not find subscriber method in "
+ subscriberClass
+ ". Maybe a missing ProGuard rule?",
e);
}
@Override
public boolean shouldCheckSuperclass() {
return shouldCheckSuperclass;
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType) {
return createSubscriberMethod(methodName, eventType, ThreadMode.POSTING, 0, false);
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode) {
return createSubscriberMethod(methodName, eventType, threadMode, 0, false);
}
protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
try {
Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
} catch (NoSuchMethodException e) {
throw new EventBusException("Could not find subscriber method in " + subscriberClass +
". Maybe a missing ProGuard rule?", e);
}
}
}
}
@@ -18,26 +18,29 @@ package org.greenrobot.eventbus.meta;
import org.greenrobot.eventbus.SubscriberMethod;
/**
* Uses {@link SubscriberMethodInfo} objects to create {@link org.greenrobot.eventbus.SubscriberMethod} objects on demand.
* Uses {@link SubscriberMethodInfo} objects to create {@link
* org.greenrobot.eventbus.SubscriberMethod} objects on demand.
*/
public class SimpleSubscriberInfo extends AbstractSubscriberInfo {
private final SubscriberMethodInfo[] methodInfos;
private final SubscriberMethodInfo[] methodInfos;
public SimpleSubscriberInfo(Class subscriberClass, boolean shouldCheckSuperclass, SubscriberMethodInfo[] methodInfos) {
super(subscriberClass, null, shouldCheckSuperclass);
this.methodInfos = methodInfos;
}
public SimpleSubscriberInfo(
Class subscriberClass, boolean shouldCheckSuperclass, SubscriberMethodInfo[] methodInfos) {
super(subscriberClass, null, shouldCheckSuperclass);
this.methodInfos = methodInfos;
}
@Override
public synchronized SubscriberMethod[] getSubscriberMethods() {
int length = methodInfos.length;
SubscriberMethod[] methods = new SubscriberMethod[length];
for (int i = 0; i < length; i++) {
SubscriberMethodInfo info = methodInfos[i];
methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
info.priority, info.sticky);
}
return methods;
@Override
public synchronized SubscriberMethod[] getSubscriberMethods() {
int length = methodInfos.length;
SubscriberMethod[] methods = new SubscriberMethod[length];
for (int i = 0; i < length; i++) {
SubscriberMethodInfo info = methodInfos[i];
methods[i] =
createSubscriberMethod(
info.methodName, info.eventType, info.threadMode, info.priority, info.sticky);
}
}
return methods;
}
}
@@ -19,11 +19,11 @@ import org.greenrobot.eventbus.SubscriberMethod;
/** Base class for generated index classes created by annotation processing. */
public interface SubscriberInfo {
Class<?> getSubscriberClass();
Class<?> getSubscriberClass();
SubscriberMethod[] getSubscriberMethods();
SubscriberMethod[] getSubscriberMethods();
SubscriberInfo getSuperSubscriberInfo();
SubscriberInfo getSuperSubscriberInfo();
boolean shouldCheckSuperclass();
boolean shouldCheckSuperclass();
}
@@ -18,27 +18,26 @@ package org.greenrobot.eventbus.meta;
import org.greenrobot.eventbus.ThreadMode;
public class SubscriberMethodInfo {
final String methodName;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
final String methodName;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
this.methodName = methodName;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
public SubscriberMethodInfo(
String methodName, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.methodName = methodName;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
public SubscriberMethodInfo(String methodName, Class<?> eventType) {
this(methodName, eventType, ThreadMode.POSTING, 0, false);
}
public SubscriberMethodInfo(String methodName, Class<?> eventType) {
this(methodName, eventType, ThreadMode.POSTING, 0, false);
}
public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode) {
this(methodName, eventType, threadMode, 0, false);
}
}
public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode) {
this(methodName, eventType, threadMode, 0, false);
}
}
@@ -23,13 +23,14 @@ import java.util.concurrent.Executors;
import java.util.logging.Level;
/**
* Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events.
* By default, uses {@link ThrowableFailureEvent}.
* <p>
* Set a custom event type using {@link Builder#failureEventType(Class)}.
* The failure event class must have a constructor with one parameter of type {@link Throwable}.
* If using ProGuard or R8 make sure the constructor of the failure event class is kept, it is accessed via reflection.
* E.g. add a rule like
* Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting
* failure events. By default, uses {@link ThrowableFailureEvent}.
*
* <p>Set a custom event type using {@link Builder#failureEventType(Class)}. The failure event class
* must have a constructor with one parameter of type {@link Throwable}. If using ProGuard or R8
* make sure the constructor of the failure event class is kept, it is accessed via reflection. E.g.
* add a rule like
*
* <pre>
* -keepclassmembers class com.example.CustomThrowableFailureEvent {
* &lt;init&gt;(java.lang.Throwable);
@@ -38,96 +39,96 @@ import java.util.logging.Level;
*/
public class AsyncExecutor {
public static class Builder {
private Executor threadPool;
private Class<?> failureEventType;
private EventBus eventBus;
public static class Builder {
private Executor threadPool;
private Class<?> failureEventType;
private EventBus eventBus;
private Builder() {
}
private Builder() {}
public Builder threadPool(Executor threadPool) {
this.threadPool = threadPool;
return this;
}
public Builder failureEventType(Class<?> failureEventType) {
this.failureEventType = failureEventType;
return this;
}
public Builder eventBus(EventBus eventBus) {
this.eventBus = eventBus;
return this;
}
public AsyncExecutor build() {
return buildForScope(null);
}
public AsyncExecutor buildForScope(Object executionContext) {
if (eventBus == null) {
eventBus = EventBus.getDefault();
}
if (threadPool == null) {
threadPool = Executors.newCachedThreadPool();
}
if (failureEventType == null) {
failureEventType = ThrowableFailureEvent.class;
}
return new AsyncExecutor(threadPool, eventBus, failureEventType, executionContext);
}
public Builder threadPool(Executor threadPool) {
this.threadPool = threadPool;
return this;
}
/** Like {@link Runnable}, but the run method may throw an exception. */
public interface RunnableEx {
void run() throws Exception;
public Builder failureEventType(Class<?> failureEventType) {
this.failureEventType = failureEventType;
return this;
}
public static Builder builder() {
return new Builder();
public Builder eventBus(EventBus eventBus) {
this.eventBus = eventBus;
return this;
}
public static AsyncExecutor create() {
return new Builder().build();
public AsyncExecutor build() {
return buildForScope(null);
}
private final Executor threadPool;
private final Constructor<?> failureEventConstructor;
private final EventBus eventBus;
private final Object scope;
private AsyncExecutor(Executor threadPool, EventBus eventBus, Class<?> failureEventType, Object scope) {
this.threadPool = threadPool;
this.eventBus = eventBus;
this.scope = scope;
try {
failureEventConstructor = failureEventType.getConstructor(Throwable.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"Failure event class must have a constructor with one parameter of type Throwable", e);
}
public AsyncExecutor buildForScope(Object executionContext) {
if (eventBus == null) {
eventBus = EventBus.getDefault();
}
if (threadPool == null) {
threadPool = Executors.newCachedThreadPool();
}
if (failureEventType == null) {
failureEventType = ThrowableFailureEvent.class;
}
return new AsyncExecutor(threadPool, eventBus, failureEventType, executionContext);
}
}
/** Posts an failure event if the given {@link RunnableEx} throws an Exception. */
public void execute(final RunnableEx runnable) {
threadPool.execute(() -> {
/** Like {@link Runnable}, but the run method may throw an exception. */
public interface RunnableEx {
void run() throws Exception;
}
public static Builder builder() {
return new Builder();
}
public static AsyncExecutor create() {
return new Builder().build();
}
private final Executor threadPool;
private final Constructor<?> failureEventConstructor;
private final EventBus eventBus;
private final Object scope;
private AsyncExecutor(
Executor threadPool, EventBus eventBus, Class<?> failureEventType, Object scope) {
this.threadPool = threadPool;
this.eventBus = eventBus;
this.scope = scope;
try {
failureEventConstructor = failureEventType.getConstructor(Throwable.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"Failure event class must have a constructor with one parameter of type Throwable", e);
}
}
/** Posts an failure event if the given {@link RunnableEx} throws an Exception. */
public void execute(final RunnableEx runnable) {
threadPool.execute(
() -> {
try {
runnable.run();
} catch (Exception e) {
Object event;
try {
runnable.run();
} catch (Exception e) {
Object event;
try {
event = failureEventConstructor.newInstance(e);
} catch (Exception e1) {
eventBus.getLogger().log(Level.SEVERE, "Original exception:", e);
throw new RuntimeException("Could not create failure event", e1);
}
if (event instanceof HasExecutionScope) {
((HasExecutionScope) event).setExecutionScope(scope);
}
eventBus.post(event);
event = failureEventConstructor.newInstance(e);
} catch (Exception e1) {
eventBus.getLogger().log(Level.SEVERE, "Original exception:", e);
throw new RuntimeException("Could not create failure event", e1);
}
if (event instanceof HasExecutionScope) {
((HasExecutionScope) event).setExecutionScope(scope);
}
eventBus.post(event);
}
});
}
}
}
@@ -24,67 +24,63 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
/**
* Maps throwables to texts for error dialogs. Use Config to configure the mapping.
*
*
* @author Markus
*/
public class ExceptionToResourceMapping {
public final Map<Class<? extends Throwable>, Integer> throwableToMsgIdMap;
public final Map<Class<? extends Throwable>, Integer> throwableToMsgIdMap;
public ExceptionToResourceMapping() {
throwableToMsgIdMap = new HashMap<>();
}
public ExceptionToResourceMapping() {
throwableToMsgIdMap = new HashMap<>();
}
/** Looks at the exception and its causes trying to find an ID. */
public Integer mapThrowable(final Throwable throwable) {
Throwable throwableToCheck = throwable;
int depthToGo = 20;
/** Looks at the exception and its causes trying to find an ID. */
public Integer mapThrowable(final Throwable throwable) {
Throwable throwableToCheck = throwable;
int depthToGo = 20;
while (true) {
Integer resId = mapThrowableFlat(throwableToCheck);
if (resId != null) {
return resId;
} else {
throwableToCheck = throwableToCheck.getCause();
depthToGo--;
if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) {
Logger logger = Logger.Default.get(); // No EventBus instance here
logger.log(Level.FINE, "No specific message resource ID found for " + throwable);
// return config.defaultErrorMsgId;
return null;
}
}
}
}
/** Mapping without checking the cause (done in mapThrowable). */
protected Integer mapThrowableFlat(Throwable throwable) {
Class<? extends Throwable> throwableClass = throwable.getClass();
Integer resId = throwableToMsgIdMap.get(throwableClass);
if (resId == null) {
Class<? extends Throwable> closestClass = null;
Set<Entry<Class<? extends Throwable>, Integer>> mappings = throwableToMsgIdMap.entrySet();
for (Entry<Class<? extends Throwable>, Integer> mapping : mappings) {
Class<? extends Throwable> candidate = mapping.getKey();
if (candidate.isAssignableFrom(throwableClass)) {
if (closestClass == null || closestClass.isAssignableFrom(candidate)) {
closestClass = candidate;
resId = mapping.getValue();
}
}
}
}
while (true) {
Integer resId = mapThrowableFlat(throwableToCheck);
if (resId != null) {
return resId;
} else {
throwableToCheck = throwableToCheck.getCause();
depthToGo--;
if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) {
Logger logger = Logger.Default.get(); // No EventBus instance here
logger.log(Level.FINE, "No specific message resource ID found for " + throwable);
// return config.defaultErrorMsgId;
return null;
}
}
}
}
public ExceptionToResourceMapping addMapping(Class<? extends Throwable> clazz, int msgId) {
throwableToMsgIdMap.put(clazz, msgId);
return this;
/** Mapping without checking the cause (done in mapThrowable). */
protected Integer mapThrowableFlat(Throwable throwable) {
Class<? extends Throwable> throwableClass = throwable.getClass();
Integer resId = throwableToMsgIdMap.get(throwableClass);
if (resId == null) {
Class<? extends Throwable> closestClass = null;
Set<Entry<Class<? extends Throwable>, Integer>> mappings = throwableToMsgIdMap.entrySet();
for (Entry<Class<? extends Throwable>, Integer> mapping : mappings) {
Class<? extends Throwable> candidate = mapping.getKey();
if (candidate.isAssignableFrom(throwableClass)) {
if (closestClass == null || closestClass.isAssignableFrom(candidate)) {
closestClass = candidate;
resId = mapping.getValue();
}
}
}
}
return resId;
}
public ExceptionToResourceMapping addMapping(Class<? extends Throwable> clazz, int msgId) {
throwableToMsgIdMap.put(clazz, msgId);
return this;
}
}
@@ -17,8 +17,7 @@
package org.greenrobot.eventbus.util;
public interface HasExecutionScope {
Object getExecutionScope();
void setExecutionScope(Object executionScope);
Object getExecutionScope();
void setExecutionScope(Object executionScope);
}
@@ -16,42 +16,41 @@
package org.greenrobot.eventbus.util;
/**
* A generic failure event, which can be used by apps to propagate thrown exceptions.
* Used as default failure event by {@link AsyncExecutor}.
* A generic failure event, which can be used by apps to propagate thrown exceptions. Used as
* default failure event by {@link AsyncExecutor}.
*/
public class ThrowableFailureEvent implements HasExecutionScope {
protected final Throwable throwable;
protected final boolean suppressErrorUi;
private Object executionContext;
protected final Throwable throwable;
protected final boolean suppressErrorUi;
private Object executionContext;
public ThrowableFailureEvent(Throwable throwable) {
this.throwable = throwable;
suppressErrorUi = false;
}
public ThrowableFailureEvent(Throwable throwable) {
this.throwable = throwable;
suppressErrorUi = false;
}
/**
* @param suppressErrorUi
* true indicates to the receiver that no error UI (e.g. dialog) should now displayed.
*/
public ThrowableFailureEvent(Throwable throwable, boolean suppressErrorUi) {
this.throwable = throwable;
this.suppressErrorUi = suppressErrorUi;
}
/**
* @param suppressErrorUi true indicates to the receiver that no error UI (e.g. dialog) should now
* displayed.
*/
public ThrowableFailureEvent(Throwable throwable, boolean suppressErrorUi) {
this.throwable = throwable;
this.suppressErrorUi = suppressErrorUi;
}
public Throwable getThrowable() {
return throwable;
}
public Throwable getThrowable() {
return throwable;
}
public boolean isSuppressErrorUi() {
return suppressErrorUi;
}
public boolean isSuppressErrorUi() {
return suppressErrorUi;
}
public Object getExecutionScope() {
return executionContext;
}
public Object getExecutionScope() {
return executionContext;
}
public void setExecutionScope(Object executionContext) {
this.executionContext = executionContext;
}
public void setExecutionScope(Object executionContext) {
this.executionContext = executionContext;
}
}
@@ -164,6 +164,7 @@ public class CPP14Lexer extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\u0093\u05b6\b\1\4"
+ "\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n"
@@ -367,6 +367,7 @@ public class CPP14Parser extends Parser {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u0093\u0840\4\2\t"
+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"
@@ -131,6 +131,7 @@ public class GroovyLexer extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2r\u03bf\b\1\4\2\t"
+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"
@@ -131,6 +131,7 @@ public class JavaLexer extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2r\u03b9\b\1\4\2\t"
+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"
@@ -247,6 +247,7 @@ public class JavaParser extends Parser {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3r\u059f\4\2\t\2\4"
+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"
@@ -32,6 +32,7 @@ public class JavadocLexer extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\16x\b\1\4\2\t\2\4"
+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"
@@ -62,6 +62,7 @@ public class JavadocParser extends Parser {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\16\u00f2\4\2\t\2"
+ "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"
@@ -193,6 +193,7 @@ public class KotlinLexer extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache();
private static final String[] _LITERAL_NAMES = makeLiteralNames();
@@ -373,6 +373,7 @@ public class KotlinParser extends Parser {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache();
private static final String[] _LITERAL_NAMES = makeLiteralNames();
@@ -26,6 +26,7 @@ public class UnicodeClasses extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\t\37\b\1\4\2\t\2"
+ "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\3\2\3\2\3\3\3\3\3\4\3"
@@ -46,6 +46,7 @@ public class XMLLexer extends Lexer {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\34\u0114\b\1\b\1"
+ "\b\1\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t"
@@ -65,6 +65,7 @@ public class XMLParser extends Parser {
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated public static final String[] tokenNames;
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\34p\4\2\t\2\4\3\t"
+ "\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4"
@@ -88,7 +88,7 @@ public abstract class ILogger {
public static ILogger newInstance(String tag) {
return createInstance(tag);
}
public static Priority priority(char priorityChar) {
for (var priority : Priority.values()) {
if (priorityChar(priority) == priorityChar) {
@@ -51,14 +51,14 @@ public class LogUtils {
return true;
}
}
public static String preProcessLogTag(String tag) {
final var regex = "[^a-z-A-Z0-9_.]";
final var matcher = Pattern.compile(regex).matcher(tag);
if (matcher.find()) {
tag = tag.replaceAll(regex, "_");
}
return tag;
}
@@ -282,11 +282,11 @@ public class JavaLanguageServer implements ILanguageServer {
}
private void startOrRestartAnalyzeTimer() {
if (VMUtils.isJvm()) {
return;
}
if (!this.timer.isStarted()) {
this.timer.start();
} else {
@@ -72,6 +72,5 @@ public class CompileTask implements AutoCloseable {
}
@Override
public void close() {
}
public void close() {}
}
@@ -104,7 +104,7 @@ public class SynchronizedTask {
}
run.run();
} catch (Throwable err) {
if(!CancelChecker.isCancelled(err)) {
if (!CancelChecker.isCancelled(err)) {
LOG.error("An error occurred", err);
}
throw err;
@@ -86,7 +86,7 @@ public class Parser {
if (module != null) {
FILE_MANAGER = SourceFileManager.forModule(module);
}
return (JavacTask)
COMPILER.getTask(
null,
@@ -57,7 +57,7 @@ public class CodeFormatProvider {
final StopWatch watch = new StopWatch("Code formatting");
final String content = params.getContent().toString();
final Formatter formatter = new Formatter(settings.getFormatterOptions());
if (params.getRange() == Range.NONE) {
String formatted;
try {
@@ -229,7 +229,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
final boolean endsWithParen = endsWithParen(contents, (int) cursor);
abortIfCancelled();
final CompilationRequest request =
new CompilationRequest(Collections.singletonList(source), partialRequest);
SynchronizedTask synchronizedTask = compiler.compile(request);
@@ -60,12 +60,12 @@ public class GenerateRecordConstructor extends Rewrite {
LOG.info("Generate default constructor for " + className + "...");
// TODO this needs to fall back on looking for inner classes and package-private classes
Path file = compiler.findTypeDeclaration(className);
if (file == CompilerProvider.NOT_FOUND) {
LOG.warn("Unable to find source file for class:", this.className);
return CANCELLED;
}
SynchronizedTask synchronizedTask = compiler.compile(file);
return synchronizedTask.get(
task -> {
@@ -85,10 +85,11 @@ public class ImplementAbstractMethods extends Rewrite {
public Map<Path, TextEdit[]> rewrite(@NonNull CompilerProvider compiler) {
final Path file = compiler.findTypeDeclaration(this.classFile);
if (file == CompilerProvider.NOT_FOUND) {
LOG.warn("Unable to find source file for class:", this.className, "classFile=", this.classFile);
LOG.warn(
"Unable to find source file for class:", this.className, "classFile=", this.classFile);
return CANCELLED;
}
final SynchronizedTask synchronizedTask = compiler.compile(file);
return synchronizedTask.get(
task -> {
@@ -50,7 +50,7 @@ public class RemoveException extends Rewrite {
final String className, methodName;
final String[] erasedParameterTypes;
final String exceptionType;
private static final ILogger LOG = ILogger.newInstance("RemoveException");
public RemoveException(
@@ -64,12 +64,12 @@ public class RemoveException extends Rewrite {
@Override
public Map<Path, TextEdit[]> rewrite(CompilerProvider compiler) {
Path file = compiler.findTypeDeclaration(className);
if (file == CompilerProvider.NOT_FOUND) {
LOG.warn("Unable to find source file for class:", this.className);
return CANCELLED;
}
SynchronizedTask synchronizedTask = compiler.compile(file);
return synchronizedTask.get(
task -> {
@@ -46,7 +46,7 @@ public class RemoveMethod extends Rewrite {
if (file == CompilerProvider.NOT_FOUND) {
return CANCELLED;
}
return compiler
.compile(file)
.get(
@@ -97,8 +97,7 @@ public class ASTFixer {
}
}
private void fixError(
@NonNull Scanner scanner, @NonNull CharSequence content, List<Edit> edits) {
private void fixError(@NonNull Scanner scanner, @NonNull CharSequence content, List<Edit> edits) {
int errPos = scanner.errPos();
if (content.charAt(errPos) == '.' && errPos > 0 && content.charAt(errPos) == '.') {
if (errPos < content.length() - 1
@@ -136,8 +135,7 @@ public class ASTFixer {
@NonNull
public static CharSequence applyInsertions(CharSequence content, List<Edit> edits) {
ImmutableList<Edit> reverseEdits =
REVERSE_INSERTION.immutableSortedCopy(edits);
ImmutableList<Edit> reverseEdits = REVERSE_INSERTION.immutableSortedCopy(edits);
StringBuilder sb = new StringBuilder(content);

Some files were not shown because too many files have changed in this diff Show More