diff --git a/.idea/misc.xml b/.idea/misc.xml index 8f0b15ced..a3c571cc4 100755 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -50,6 +50,7 @@ + diff --git a/app/src/main/assets/data/common/gradle-plugin.zip b/app/src/main/assets/data/common/gradle-plugin.zip index 2c9f48607..19e3754b8 100644 Binary files a/app/src/main/assets/data/common/gradle-plugin.zip and b/app/src/main/assets/data/common/gradle-plugin.zip differ diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java index 1e92eeda6..69baba4db 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java +++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java @@ -20,4 +20,6 @@ package com.itsaky.androidide.fragments.attr; /** * @author Akash Yadav */ -public class BooleanEditor extends BaseValueEditorFragment {} +public class BooleanEditor extends BaseValueEditorFragment { + +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java index d2337385d..b703351ba 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java +++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java @@ -34,6 +34,7 @@ import com.itsaky.androidide.adapters.AttrValueCompletionAdapter; import com.itsaky.androidide.databinding.LayoutDimensionAttrEditorBinding; import com.itsaky.androidide.utils.Logger; import com.itsaky.androidide.utils.TextWatcherAdapter; +import com.itsaky.inflater.values.FrameworkValues; import com.itsaky.inflater.values.ValuesTableFactory; import java.util.ArrayList; @@ -45,124 +46,129 @@ import java.util.stream.Collectors; * @author Akash Yadav */ public class DimensionEditor extends BaseValueEditorFragment { - - private static final Logger LOG = Logger.instance("DimensionEditor"); + + private static final Logger LOG = Logger.instance ("DimensionEditor"); public TextWatcherAdapter dimensionInputWatcher; public TextWatcherAdapter dimensionResInputWatcher; private LayoutDimensionAttrEditorBinding binding; private String[] dimensionUnits; - + @Nullable @Override - public View onCreateView( + public View onCreateView ( @NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - this.binding = LayoutDimensionAttrEditorBinding.inflate(inflater, container, false); - return this.binding.getRoot(); + this.binding = LayoutDimensionAttrEditorBinding.inflate (inflater, container, false); + return this.binding.getRoot (); } - + @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - + public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated (view, savedInstanceState); + final var dimensionInput = - Objects.requireNonNull(this.binding.dimensionInput.getEditText()); + Objects.requireNonNull (this.binding.dimensionInput.getEditText ()); if (dimensionInputWatcher != null) { - dimensionInput.removeTextChangedListener(dimensionInputWatcher); + dimensionInput.removeTextChangedListener (dimensionInputWatcher); } - + dimensionInputWatcher = - new TextWatcherAdapter() { + new TextWatcherAdapter () { @Override - public void afterTextChanged(@NonNull Editable s) { - final var text = s.toString().trim(); + public void afterTextChanged (@NonNull Editable s) { + final var text = s.toString ().trim (); final var unit = - getDimensionUnits()[binding.unitSelector.getSelectedItemPosition()]; - + getDimensionUnits ()[binding.unitSelector.getSelectedItemPosition ()]; + // This will call CommonParseUtils#parseDimension - notifyValueChanged(text.concat(unit)); + notifyValueChanged (text.concat (unit)); } }; - - dimensionInput.addTextChangedListener(dimensionInputWatcher); - + + dimensionInput.addTextChangedListener (dimensionInputWatcher); + final var dimensionResInput = (MaterialAutoCompleteTextView) - Objects.requireNonNull(binding.dimensionResInput.getEditText()); - + Objects.requireNonNull (binding.dimensionResInput.getEditText ()); + if (dimensionResInputWatcher != null) { - dimensionResInput.removeTextChangedListener(dimensionResInputWatcher); + dimensionResInput.removeTextChangedListener (dimensionResInputWatcher); } - + dimensionResInputWatcher = - new TextWatcherAdapter() { + new TextWatcherAdapter () { @Override - public void afterTextChanged(@NonNull Editable s) { - final var text = s.toString().trim(); - if (TextUtils.isEmpty(text)) { + public void afterTextChanged (@NonNull Editable s) { + final var text = s.toString ().trim (); + if (TextUtils.isEmpty (text)) { return; } - - notifyValueChanged(text); + + notifyValueChanged (text); } }; - - dimensionResInput.addTextChangedListener(dimensionResInputWatcher); - + + dimensionResInput.addTextChangedListener (dimensionResInputWatcher); + final var future = - CompletableFuture.supplyAsync( + CompletableFuture.supplyAsync ( () -> { - final var list = new ArrayList(); - final var tables = ValuesTableFactory.getAllTables(); - for (var entry : tables.entrySet()) { - final var dimens = entry.getValue().getTable("dimen"); + final var list = new ArrayList (); + final var tables = ValuesTableFactory.getAllTables (); + for (var entry : tables.entrySet ()) { + final var dimens = entry.getValue ().getTable ("dimen"); if (dimens != null) { - list.addAll( - dimens.keySet().stream() - .map("@dimen/"::concat) - .collect(Collectors.toSet())); + list.addAll ( + dimens.keySet ().stream () + .map ("@dimen/"::concat) + .collect (Collectors.toSet ())); } } - + + list.addAll (FrameworkValues.listDimens () + .stream () + .map ("@android:dimen/"::concat) + .collect (Collectors.toList ()) + ); return list; }); - future.whenComplete( + future.whenComplete ( (list, throwable) -> { - if (list == null || list.isEmpty()) { - LOG.error("No completion items found"); + if (list == null || list.isEmpty ()) { + LOG.error ("No completion items found"); return; } - - LOG.debug("Found", list.size(), "dimension resources for completion"); - - ThreadUtils.runOnUiThread( + + LOG.debug ("Found", list.size (), "dimension resources for completion"); + + ThreadUtils.runOnUiThread ( () -> { final var adapter = - new AttrValueCompletionAdapter(requireContext(), list); - dimensionResInput.setThreshold(1); - dimensionResInput.setAdapter(adapter); - adapter.notifyDataSetChanged(); + new AttrValueCompletionAdapter (requireContext (), list); + dimensionResInput.setThreshold (1); + dimensionResInput.setAdapter (adapter); + adapter.notifyDataSetChanged (); }); }); } - + @NonNull - private String[] getDimensionUnits() { + private String[] getDimensionUnits () { if (dimensionUnits == null) { dimensionUnits = - requireContext().getResources().getStringArray(R.array.dimension_units); + requireContext ().getResources ().getStringArray (R.array.dimension_units); } - + return dimensionUnits; } - + @Override - protected void notifyValueChanged(@NonNull String newValue) { + protected void notifyValueChanged (@NonNull String newValue) { try { - super.notifyValueChanged(newValue); + super.notifyValueChanged (newValue); } catch (Throwable e) { - LOG.error("Unable to update dimension value to '" + newValue + "'", e); + LOG.error ("Unable to update dimension value to '" + newValue + "'", e); } } } diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java index e02a95686..3c40809a5 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java +++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java @@ -26,13 +26,11 @@ import com.google.android.material.chip.Chip; import com.google.android.material.chip.ChipGroup; import com.itsaky.androidide.utils.Logger; -/** - * @author Akash Yadav - */ +/** @author Akash Yadav */ public class EnumEditor extends FixedValueEditor { private static final Logger LOG = Logger.instance("EnumEditor"); - + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); diff --git a/app/src/main/java/com/itsaky/androidide/handlers/BuildServiceHandler.java b/app/src/main/java/com/itsaky/androidide/handlers/BuildServiceHandler.java index ac8ee107a..c15d300e9 100755 --- a/app/src/main/java/com/itsaky/androidide/handlers/BuildServiceHandler.java +++ b/app/src/main/java/com/itsaky/androidide/handlers/BuildServiceHandler.java @@ -1,4 +1,4 @@ -/************************************************************************************ +/* * This file is part of AndroidIDE. * * AndroidIDE is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with AndroidIDE. If not, see . * - **************************************************************************************/ + */ package com.itsaky.androidide.handlers; import android.view.View; @@ -36,223 +36,229 @@ import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; public class BuildServiceHandler extends IDEHandler implements BuildListener { - + private IDEService service; private boolean shouldInstallApk = false; - - public BuildServiceHandler(Provider provider) { - super(provider); + + public BuildServiceHandler (Provider provider) { + super (provider); } - - public IDEService getService() { + + public IDEService getService () { return service; } - + @Override - public void start() { - if (this.activity() == null) { - throwNPE(); - } - - AndroidProject project = provider.provideAndroidProject(); - if (project == null) { - throwNPE(); - } - - if (project.getProjectPath() == null) { - throwNPE(); - } - - this.service = new IDEService(new File(project.getProjectPath())); - this.service.setListener(this); + public void start () { + Objects.requireNonNull (this.activity ()); + + AndroidProject project = provider.provideAndroidProject (); + Objects.requireNonNull (project); + Objects.requireNonNull (project.getProjectPath ()); + + this.service = new IDEService (new File (project.getProjectPath ())); + this.service.setListener (this); } - + @Override - public void stop() { - this.service.stopAllDaemons(); - this.service.exit(); + public void stop () { + this.service.stopAllDaemons (); + this.service.exit (); } - + @Override - public void onBuildModified() { + public void onBuildModified () { // Does nothing currently } - + @Override - public void onProjectLoaded(IDEProject project, Optional appModule) { - project.iconPath = provider.provideAndroidProject().getIconPath(); - activity().setIDEProject(project); - - if (appModule.isPresent()) { - IDEModule app = appModule.get(); - activity().setStatus(activity().getString(R.string.msg_starting_completion)); - + public void onProjectLoaded (IDEProject project, Optional appModule) { + project.iconPath = provider.provideAndroidProject ().getIconPath (); + activity ().setIDEProject (project); + + if (appModule.isPresent ()) { + IDEModule app = appModule.get (); + activity ().setStatus (activity ().getString (R.string.msg_starting_completion)); + final List paths = - app.dependencies.stream() - .filter(this::isClasspathValid) - .collect(Collectors.toList()); - - provider.provideAndroidProject().setClassPaths(paths); - + app.dependencies.stream () + .filter (this::isClasspathValid) + .collect (Collectors.toList ()); + + provider.provideAndroidProject ().setClassPaths (paths); + File androidJar = - new File( + new File ( Environment.ANDROID_HOME, - String.format("platforms/%s/android.jar", app.compileSdkVersion)); - if (androidJar.exists()) { - Environment.setBootClasspath(androidJar); - provider.provideAndroidProject().addClasspath(androidJar.getAbsolutePath()); - activity().updateServices(); - } else activity().setStatus("android.jar not found!"); - } else activity().setStatus("Cannot get :app module..."); - } - - @Override - public void onStartingGradleDaemon(GradleTask task) { - activity().setStatus(activity().getString(R.string.msg_starting_daemon)); - } - - @Override - public void onRunTask(GradleTask task, String name) { - if (task != null && task.canOutput()) { - activity().setStatus(service.typeString(task.getTaskID()) + " " + name); + String.format ("platforms/%s/android.jar", app.compileSdkVersion)); + if (androidJar.exists ()) { + Environment.setBootClasspath (androidJar); + provider.provideAndroidProject ().addClasspath (androidJar.getAbsolutePath ()); + activity ().updateServices (); + } else { + activity ().setStatus ("android.jar not found!"); + } + } else { + activity ().setStatus ("Cannot get :app module..."); } } - + @Override - public void onBuildSuccessful(GradleTask task, String msg) { - appendOutput(task, msg); - if (task == null || activity() == null) return; - if (task.canOutput()) { - activity().setStatus(msg); + public void onStartingGradleDaemon (GradleTask task) { + activity ().setStatus (activity ().getString (R.string.msg_starting_daemon)); + } + + @Override + public void onRunTask (GradleTask task, String name) { + if (task != null && task.canOutput ()) { + activity ().setStatus (service.typeString (task.getTaskID ()) + " " + name); } - + } + + @Override + public void onBuildSuccessful (GradleTask task, String msg) { + appendOutput (task, msg); + if (task == null || activity () == null) { + return; + } + if (task.canOutput ()) { + activity ().setStatus (msg); + } + // If this task generates APK, ask user if he/she wants to install them if (shouldInstallApk && task instanceof ApkGeneratingTask) { - final IDEProject project = activity().provideIDEProject(); + final IDEProject project = activity ().provideIDEProject (); final Optional app = - project.getModuleByPath(":app"); // TODO Handle multiple application modules - if (app.isPresent()) { - final String path = app.get().projectDir; + project.getModuleByPath (":app"); // TODO Handle multiple application modules + if (app.isPresent ()) { + final String path = app.get ().projectDir; if (path != null) { - final File buildDir = new File(path, "build"); - installApks(((ApkGeneratingTask) task).getApks(buildDir)); + final File buildDir = new File (path, "build"); + installApks (((ApkGeneratingTask) task).getApks (buildDir)); } } } - - activity() - .getApp() - .getPrefManager() - .putBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false); - activity().invalidateOptionsMenu(); - activity().getBinding().buildProgressIndicator.setVisibility(View.GONE); + + activity () + .getApp () + .getPrefManager () + .putBoolean (PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false); + activity ().invalidateOptionsMenu (); + activity ().getBinding ().buildProgressIndicator.setVisibility (View.GONE); } - + @Override - public void onBuildFailed(GradleTask task, String msg) { - appendOutput(task, msg); - if (task == null) return; - if (task.canOutput()) { - activity().setStatus(msg); - } - - activity() - .getApp() - .getPrefManager() - .putBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false); - activity().invalidateOptionsMenu(); - activity().getBinding().buildProgressIndicator.setVisibility(View.GONE); - } - - @Override - public void saveFiles() { - activity().saveAll(false, false); - } - - @Override - public void appendOutput(GradleTask task, CharSequence text) { - if (text == null) return; - if (task != null && !task.canOutput()) { + public void onBuildFailed (GradleTask task, String msg) { + appendOutput (task, msg); + if (task == null) { return; } - - activity().appendBuildOut(text.toString()); + if (task.canOutput ()) { + activity ().setStatus (msg); + } + + activity () + .getApp () + .getPrefManager () + .putBoolean (PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false); + activity ().invalidateOptionsMenu (); + activity ().getBinding ().buildProgressIndicator.setVisibility (View.GONE); } - + @Override - public void prepareBuild() { + public void saveFiles () { + activity ().saveAll (false, false); + } + + @Override + public void appendOutput (GradleTask task, CharSequence text) { + if (text == null) { + return; + } + if (task != null && !task.canOutput ()) { + return; + } + + activity ().appendBuildOut (text.toString ()); + } + + @Override + public void prepareBuild () { boolean isFirstBuild = - activity() - .getApp() - .getPrefManager() - .getBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, true); - activity() - .setStatus( - activity() - .getString( + activity () + .getApp () + .getPrefManager () + .getBoolean (PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, true); + activity () + .setStatus ( + activity () + .getString ( isFirstBuild ? R.string.preparing_first : R.string.preparing)); if (isFirstBuild) { - activity().showFirstBuildNotice(); + activity ().showFirstBuildNotice (); } - activity().getBinding().buildProgressIndicator.setVisibility(View.VISIBLE); + activity ().getBinding ().buildProgressIndicator.setVisibility (View.VISIBLE); } - - public void setShouldInstallApk(boolean install) { + + public void setShouldInstallApk (boolean install) { this.shouldInstallApk = install; } - - public void assembleDebug(boolean shouldInstallApk) { - setShouldInstallApk(shouldInstallApk); - getService().assembleDebug(shouldInstallApk); + + public void assembleDebug (boolean shouldInstallApk) { + setShouldInstallApk (shouldInstallApk); + getService ().assembleDebug (shouldInstallApk); } - - private boolean isClasspathValid(String path) { - if (path == null || path.trim().length() <= 0 || path.trim().equals("/")) return false; - File file = new File(path); - return file.isFile() - && file.getName().endsWith(".jar") - /** Release R.jar shouldn't be included in classpath */ - && !file.getAbsolutePath().endsWith("/release/R.jar"); + + private boolean isClasspathValid (String path) { + if (path == null || path.trim ().length () <= 0 || path.trim ().equals ("/")) { + return false; + } + File file = new File (path); + return file.isFile () + && file.getName ().endsWith (".jar") + // Release R.jar shouldn't be included in classpath + && !file.getAbsolutePath ().endsWith ("/release/R.jar"); } - - private void installApks(final Set apks) { - if (activity() == null || apks == null || apks.isEmpty()) { + + private void installApks (final Set apks) { + if (activity () == null || apks == null || apks.isEmpty ()) { return; } - - if (apks.size() == 1) { - activity().install(apks.iterator().next()); + + if (apks.size () == 1) { + activity ().install (apks.iterator ().next ()); } else { - final List files = new ArrayList(apks); + final List files = new ArrayList<> (apks); final MaterialAlertDialogBuilder builder = - DialogUtils.newMaterialDialogBuilder(activity()); - builder.setTitle(activity().getString(R.string.title_install_apks)); - builder.setItems( - getNames(files), + DialogUtils.newMaterialDialogBuilder (activity ()); + builder.setTitle (activity ().getString (R.string.title_install_apks)); + builder.setItems ( + getNames (files), (d, w) -> { - d.dismiss(); - activity().install(files.get(w)); + d.dismiss (); + activity ().install (files.get (w)); }); - builder.show(); + builder.show (); } } - - private CharSequence[] getNames(final Collection apks) { - final String[] names = new String[apks.size()]; - + + private CharSequence[] getNames (final Collection apks) { + final String[] names = new String[apks.size ()]; + int i = 0; for (File apk : apks) { - names[i] = apk.getName(); + names[i] = apk.getName (); ++i; } - + return names; } } diff --git a/app/src/main/java/com/itsaky/androidide/handlers/FileOptionsHandler.java b/app/src/main/java/com/itsaky/androidide/handlers/FileOptionsHandler.java index 64b685ab6..29289ac95 100755 --- a/app/src/main/java/com/itsaky/androidide/handlers/FileOptionsHandler.java +++ b/app/src/main/java/com/itsaky/androidide/handlers/FileOptionsHandler.java @@ -41,404 +41,403 @@ import java.util.regex.Pattern; public class FileOptionsHandler extends IDEHandler implements OptionsListFragment.OnOptionsClickListener { - + public static final String RES_PATH_REGEX = "/.*/src/.*/res"; public static final String LAYOUT_RES_PATH_REGEX = "/.*/src/.*/res/layout"; public static final String MENU_RES_PATH_REGEX = "/.*/src/.*/res/menu"; public static final String DRAWABLE_RES_PATH_REGEX = "/.*/src/.*/res/drawable"; public static final String JAVA_PATH_REGEX = "/.*/src/.*/java"; - - public FileOptionsHandler(Provider provider) { - super(provider); + + public FileOptionsHandler (Provider provider) { + super (provider); } - + @Override - public void start() { - if (activity() == null) { - throwNPE(); - } + public void start () { + Objects.requireNonNull (this.activity ()); } - + @Override - public void stop() {} - + public void stop () { + } + @Override - public void onOptionsClick(SheetOption option) { + public void onOptionsClick (SheetOption option) { if (option.extra instanceof File) { final File f = (File) option.extra; switch (option.id) { case 0: - ClipboardUtils.copyText("[AndroidIDE] Copied File Path", f.getAbsolutePath()); - activity().getApp().toast(R.string.copied, Toaster.Type.SUCCESS); + ClipboardUtils.copyText ("[AndroidIDE] Copied File Path", f.getAbsolutePath ()); + activity ().getApp ().toast (R.string.copied, Toaster.Type.SUCCESS); break; case 1: - renameFile(f); + renameFile (f); break; case 2: - delete(f); + delete (f); break; case 3: - createNewFile(f); + createNewFile (f); break; case 4: - createNewFolder(f); + createNewFolder (f); break; } } } - - private void createNewFile(File f) { - createNewFile(f, false); + + private void createNewFile (File f) { + createNewFile (f, false); } - - private void createNewFile(final File f, boolean forceUnknownType) { + + private void createNewFile (final File f, boolean forceUnknownType) { if (forceUnknownType) { - createNewEmptyFile(f); + createNewEmptyFile (f); } else { final boolean isJava = - Pattern.compile( - Pattern.quote(androidProject().getProjectPath()) - + JAVA_PATH_REGEX) - .matcher(f.getAbsolutePath()) - .find(); + Pattern.compile ( + Pattern.quote (androidProject ().getProjectPath ()) + + JAVA_PATH_REGEX) + .matcher (f.getAbsolutePath ()) + .find (); final boolean isRes = - Pattern.compile( - Pattern.quote(androidProject().getProjectPath()) - + RES_PATH_REGEX) - .matcher(f.getAbsolutePath()) - .find(); + Pattern.compile ( + Pattern.quote (androidProject ().getProjectPath ()) + + RES_PATH_REGEX) + .matcher (f.getAbsolutePath ()) + .find (); final boolean isLayoutRes = - Pattern.compile( - Pattern.quote(androidProject().getProjectPath()) - + LAYOUT_RES_PATH_REGEX) - .matcher(f.getAbsolutePath()) - .find(); + Pattern.compile ( + Pattern.quote (androidProject ().getProjectPath ()) + + LAYOUT_RES_PATH_REGEX) + .matcher (f.getAbsolutePath ()) + .find (); final boolean isMenuRes = - Pattern.compile( - Pattern.quote(androidProject().getProjectPath()) - + MENU_RES_PATH_REGEX) - .matcher(f.getAbsolutePath()) - .find(); + Pattern.compile ( + Pattern.quote (androidProject ().getProjectPath ()) + + MENU_RES_PATH_REGEX) + .matcher (f.getAbsolutePath ()) + .find (); final boolean isDrawableRes = - Pattern.compile( - Pattern.quote(androidProject().getProjectPath()) - + DRAWABLE_RES_PATH_REGEX) - .matcher(f.getAbsolutePath()) - .find(); + Pattern.compile ( + Pattern.quote (androidProject ().getProjectPath ()) + + DRAWABLE_RES_PATH_REGEX) + .matcher (f.getAbsolutePath ()) + .find (); if (isJava) { - createJavaClass(f); - } else if (isLayoutRes && f.getName().equals("layout")) { - createLayoutRes(f); - } else if (isMenuRes && f.getName().equals("menu")) { - createMenuRes(f); - } else if (isDrawableRes && f.getName().equals("drawable")) { - createDrawableRes(f); - } else if (isRes && f.getName().equals("res")) { - createNewResource(f); + createJavaClass (f); + } else if (isLayoutRes && f.getName ().equals ("layout")) { + createLayoutRes (f); + } else if (isMenuRes && f.getName ().equals ("menu")) { + createMenuRes (f); + } else if (isDrawableRes && f.getName ().equals ("drawable")) { + createDrawableRes (f); + } else if (isRes && f.getName ().equals ("res")) { + createNewResource (f); } else { - createNewEmptyFile(f); + createNewEmptyFile (f); } } } - - private void createJavaClass(final File f) { - final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity()); + + private void createJavaClass (final File f) { + final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (activity ()); final LayoutCreateFileJavaBinding binding = - LayoutCreateFileJavaBinding.inflate(activity().getLayoutInflater()); - builder.setView(binding.getRoot()); - builder.setTitle(R.string.new_java_class); - builder.setPositiveButton( + LayoutCreateFileJavaBinding.inflate (activity ().getLayoutInflater ()); + builder.setView (binding.getRoot ()); + builder.setTitle (R.string.new_java_class); + builder.setPositiveButton ( R.string.text_create, (p1, p2) -> { - p1.dismiss(); + p1.dismiss (); final String name = - Objects.requireNonNull(binding.name.getEditText()) - .getText() - .toString() - .trim(); - final String pkgName = ProjectWriter.getPackageName(f); - if (pkgName == null || pkgName.trim().length() <= 0) { - activity() - .getApp() - .toast(R.string.msg_get_package_failed, Toaster.Type.ERROR); + Objects.requireNonNull (binding.name.getEditText ()) + .getText () + .toString () + .trim (); + final String pkgName = ProjectWriter.getPackageName (f); + if (pkgName == null || pkgName.trim ().length () <= 0) { + activity () + .getApp () + .toast (R.string.msg_get_package_failed, Toaster.Type.ERROR); } else { - final int id = binding.typeGroup.getCheckedButtonId(); - final var javaName = name.endsWith(".java") ? name : name.concat(".java"); + final int id = binding.typeGroup.getCheckedButtonId (); + final var javaName = name.endsWith (".java") ? name : name.concat (".java"); final var className = - !name.contains(".") + !name.contains (".") ? name - : name.substring(0, name.lastIndexOf(".")); - if (id == binding.typeClass.getId()) { - createFile( - f, javaName, ProjectWriter.createJavaClass(pkgName, className)); - } else if (id == binding.typeInterface.getId()) { - createFile( + : name.substring (0, name.lastIndexOf (".")); + if (id == binding.typeClass.getId ()) { + createFile ( + f, javaName, ProjectWriter.createJavaClass (pkgName, className)); + } else if (id == binding.typeInterface.getId ()) { + createFile ( f, javaName, - ProjectWriter.createJavaInterface(pkgName, className)); - } else if (id == binding.typeEnum.getId()) { - createFile( - f, javaName, ProjectWriter.createJavaEnum(pkgName, className)); - } else if (id == binding.typeActivity.getId()) { - createFile( - f, javaName, ProjectWriter.createActivity(pkgName, className)); + ProjectWriter.createJavaInterface (pkgName, className)); + } else if (id == binding.typeEnum.getId ()) { + createFile ( + f, javaName, ProjectWriter.createJavaEnum (pkgName, className)); + } else if (id == binding.typeActivity.getId ()) { + createFile ( + f, javaName, ProjectWriter.createActivity (pkgName, className)); } else { - createFile(f, name, ""); + createFile (f, name, ""); } } }); - builder.setNegativeButton(android.R.string.cancel, null); - builder.setCancelable(false); - builder.create().show(); + builder.setNegativeButton (android.R.string.cancel, null); + builder.setCancelable (false); + builder.create ().show (); } - - private void createLayoutRes(File f) { - createNewFileWithContent( - Environment.mkdirIfNotExits(f), ProjectWriter.createLayout(), ".xml"); + + private void createLayoutRes (File f) { + createNewFileWithContent ( + Environment.mkdirIfNotExits (f), ProjectWriter.createLayout (), ".xml"); } - - private void createMenuRes(File f) { - createNewFileWithContent( - Environment.mkdirIfNotExits(f), ProjectWriter.createMenu(), ".xml"); + + private void createMenuRes (File f) { + createNewFileWithContent ( + Environment.mkdirIfNotExits (f), ProjectWriter.createMenu (), ".xml"); } - - private void createDrawableRes(File f) { - createNewFileWithContent( - Environment.mkdirIfNotExits(f), ProjectWriter.createDrawable(), ".xml"); + + private void createDrawableRes (File f) { + createNewFileWithContent ( + Environment.mkdirIfNotExits (f), ProjectWriter.createDrawable (), ".xml"); } - - private void createNewResource(File f) { + + private void createNewResource (File f) { final String[] labels = { - activity().getString(R.string.restype_drawable), - activity().getString(R.string.restype_layout), - activity().getString(R.string.restype_menu), - activity().getString(R.string.restype_other) + activity ().getString (R.string.restype_drawable), + activity ().getString (R.string.restype_layout), + activity ().getString (R.string.restype_menu), + activity ().getString (R.string.restype_other) }; - final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity()); - builder.setTitle(R.string.new_xml_resource); - builder.setItems( + final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (activity ()); + builder.setTitle (R.string.new_xml_resource); + builder.setItems ( labels, (dialogInterface, position) -> { if (position == 0) { - createDrawableRes(new File(f, "drawable")); + createDrawableRes (new File (f, "drawable")); } else if (position == 1) { - createLayoutRes(new File(f, "layout")); + createLayoutRes (new File (f, "layout")); } else if (position == 2) { - createMenuRes(new File(f, "menu")); + createMenuRes (new File (f, "menu")); } else if (position == 3) { - createNewFile(f, true); + createNewFile (f, true); } }); - builder.create().show(); + builder.create ().show (); } - - private void createNewEmptyFile(File f) { - createNewFileWithContent(f, ""); + + private void createNewEmptyFile (File f) { + createNewFileWithContent (f, ""); } - - private void createNewFileWithContent(File f, String content) { - createNewFileWithContent(f, content, null); + + private void createNewFileWithContent (File f, String content) { + createNewFileWithContent (f, content, null); } - - private void createNewFileWithContent(File folder, String content, String extension) { + + private void createNewFileWithContent (File folder, String content, String extension) { final LayoutDialogTextInputBinding binding = - LayoutDialogTextInputBinding.inflate(activity().getLayoutInflater()); - final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity()); - - Objects.requireNonNull(binding.name.getEditText()).setHint(R.string.file_name); - - builder.setTitle(R.string.new_file); - builder.setMessage( - activity() - .getString(R.string.msg_can_contain_slashes) - .concat("\n\n") - .concat( - activity() - .getString( + LayoutDialogTextInputBinding.inflate (activity ().getLayoutInflater ()); + final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (activity ()); + + Objects.requireNonNull (binding.name.getEditText ()).setHint (R.string.file_name); + + builder.setTitle (R.string.new_file); + builder.setMessage ( + activity () + .getString (R.string.msg_can_contain_slashes) + .concat ("\n\n") + .concat ( + activity () + .getString ( R.string.msg_newfile_dest, - folder.getAbsolutePath()))); - builder.setView(binding.getRoot()); - builder.setCancelable(false); - builder.setPositiveButton( + folder.getAbsolutePath ()))); + builder.setView (binding.getRoot ()); + builder.setCancelable (false); + builder.setPositiveButton ( R.string.text_create, (p1, p2) -> { - p1.dismiss(); - String name = binding.name.getEditText().getText().toString().trim(); - if (extension != null && extension.trim().length() > 0) { - name = name.endsWith(extension) ? name : name.concat(extension); + p1.dismiss (); + String name = binding.name.getEditText ().getText ().toString ().trim (); + if (extension != null && extension.trim ().length () > 0) { + name = name.endsWith (extension) ? name : name.concat (extension); } - createFile(folder, name, content); + createFile (folder, name, content); }); - builder.setNegativeButton(android.R.string.cancel, null); - builder.create().show(); + builder.setNegativeButton (android.R.string.cancel, null); + builder.create ().show (); } - - private void createFile(File f, String name, String content) { - if (name.length() > 0 && name.length() <= 40 && !name.startsWith("/")) { - final File file = new File(f, name); - if (file.exists()) { - activity().getApp().toast(R.string.msg_file_exists, Toaster.Type.ERROR); + + private void createFile (File f, String name, String content) { + if (name.length () > 0 && name.length () <= 40 && !name.startsWith ("/")) { + final File file = new File (f, name); + if (file.exists ()) { + activity ().getApp ().toast (R.string.msg_file_exists, Toaster.Type.ERROR); } else { - if (FileIOUtils.writeFileFromString(file, content)) { + if (FileIOUtils.writeFileFromString (file, content)) { // TODO Notify language servers about file created event - activity().getApp().toast(R.string.msg_file_created, Toaster.Type.SUCCESS); - if (activity().getLastHoldTreeNode() != null) { - TreeNode node = new TreeNode(file); - node.setViewHolder(new FileTreeViewHolder(activity())); - activity().getLastHoldTreeNode().addChild(node); - activity() - .getFileTreeFragment() - .expandNode(activity().getLastHoldTreeNode()); + activity ().getApp ().toast (R.string.msg_file_created, Toaster.Type.SUCCESS); + if (activity ().getLastHoldTreeNode () != null) { + TreeNode node = new TreeNode (file); + node.setViewHolder (new FileTreeViewHolder (activity ())); + activity ().getLastHoldTreeNode ().addChild (node); + activity () + .getFileTreeFragment () + .expandNode (activity ().getLastHoldTreeNode ()); } else { - activity().getFileTreeFragment().listProjectFiles(); + activity ().getFileTreeFragment ().listProjectFiles (); } } else { - activity() - .getApp() - .toast(R.string.msg_file_creation_failed, Toaster.Type.ERROR); + activity () + .getApp () + .toast (R.string.msg_file_creation_failed, Toaster.Type.ERROR); } } } else { - activity().getApp().toast(R.string.msg_invalid_name, Toaster.Type.ERROR); + activity ().getApp ().toast (R.string.msg_invalid_name, Toaster.Type.ERROR); } } - - private void createNewFolder(File f) { + + private void createNewFolder (File f) { final LayoutDialogTextInputBinding binding = - LayoutDialogTextInputBinding.inflate(activity().getLayoutInflater()); - final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity()); - - Objects.requireNonNull(binding.name.getEditText()).setHint(R.string.folder_name); - - builder.setTitle(R.string.new_folder); - builder.setMessage(R.string.msg_can_contain_slashes); - builder.setView(binding.getRoot()); - builder.setCancelable(false); - builder.setPositiveButton( + LayoutDialogTextInputBinding.inflate (activity ().getLayoutInflater ()); + final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (activity ()); + + Objects.requireNonNull (binding.name.getEditText ()).setHint (R.string.folder_name); + + builder.setTitle (R.string.new_folder); + builder.setMessage (R.string.msg_can_contain_slashes); + builder.setView (binding.getRoot ()); + builder.setCancelable (false); + builder.setPositiveButton ( R.string.text_create, (p1, p2) -> { - p1.dismiss(); - final String name = binding.name.getEditText().getText().toString().trim(); - if (name.length() > 0 && name.length() <= 40 && !name.startsWith("/")) { - final File file = new File(f, name); - if (file.exists()) { - activity() - .getApp() - .toast(R.string.msg_folder_exists, Toaster.Type.ERROR); + p1.dismiss (); + final String name = binding.name.getEditText ().getText ().toString ().trim (); + if (name.length () > 0 && name.length () <= 40 && !name.startsWith ("/")) { + final File file = new File (f, name); + if (file.exists ()) { + activity () + .getApp () + .toast (R.string.msg_folder_exists, Toaster.Type.ERROR); } else { - if (file.mkdirs()) { - activity() - .getApp() - .toast(R.string.msg_folder_created, Toaster.Type.SUCCESS); - if (activity().getLastHoldTreeNode() != null) { - TreeNode node = new TreeNode(file); - node.setViewHolder(new FileTreeViewHolder(activity())); - activity().getLastHoldTreeNode().addChild(node); - activity() - .getFileTreeFragment() - .expandNode(activity().getLastHoldTreeNode()); + if (file.mkdirs ()) { + activity () + .getApp () + .toast (R.string.msg_folder_created, Toaster.Type.SUCCESS); + if (activity ().getLastHoldTreeNode () != null) { + TreeNode node = new TreeNode (file); + node.setViewHolder (new FileTreeViewHolder (activity ())); + activity ().getLastHoldTreeNode ().addChild (node); + activity () + .getFileTreeFragment () + .expandNode (activity ().getLastHoldTreeNode ()); } else { - activity().getFileTreeFragment().listProjectFiles(); + activity ().getFileTreeFragment ().listProjectFiles (); } } else { - activity() - .getApp() - .toast( + activity () + .getApp () + .toast ( R.string.msg_folder_creation_failed, Toaster.Type.ERROR); } } } else { - activity().getApp().toast(R.string.msg_invalid_name, Toaster.Type.ERROR); + activity ().getApp ().toast (R.string.msg_invalid_name, Toaster.Type.ERROR); } }); - builder.setNegativeButton(android.R.string.cancel, null); - builder.create().show(); + builder.setNegativeButton (android.R.string.cancel, null); + builder.create ().show (); } - - private void delete(final File f) { - MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity()); - builder.setNegativeButton(R.string.no, null) - .setPositiveButton( + + private void delete (final File f) { + MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (activity ()); + builder.setNegativeButton (R.string.no, null) + .setPositiveButton ( R.string.yes, (p1, p2) -> { - p1.dismiss(); - final boolean deleted = FileUtils.delete(f); - activity() - .getApp() - .toast( + p1.dismiss (); + final boolean deleted = FileUtils.delete (f); + activity () + .getApp () + .toast ( deleted ? R.string.deleted : R.string.delete_failed, deleted ? Toaster.Type.SUCCESS : Toaster.Type.ERROR); if (deleted) { // TODO Notify language servers about file delete event - if (activity().getLastHoldTreeNode() != null) { - TreeNode parent = activity().getLastHoldTreeNode().getParent(); - parent.deleteChild(activity().getLastHoldTreeNode()); - activity().getFileTreeFragment().expandNode(parent); + if (activity ().getLastHoldTreeNode () != null) { + TreeNode parent = activity ().getLastHoldTreeNode ().getParent (); + parent.deleteChild (activity ().getLastHoldTreeNode ()); + activity ().getFileTreeFragment ().expandNode (parent); } else { - activity().getFileTreeFragment().listProjectFiles(); + activity ().getFileTreeFragment ().listProjectFiles (); } - - final var frag = activity().getEditorForFile(f); + + final var frag = activity ().getEditorForFile (f); if (frag != null) { - activity() - .closeFile( - activity() - .findIndexOfEditorByFile( - frag.getFile())); + activity () + .closeFile ( + activity () + .findIndexOfEditorByFile ( + frag.getFile ())); } } }) - .setTitle(R.string.title_confirm_delete) - .setMessage( - activity() - .getString( + .setTitle (R.string.title_confirm_delete) + .setMessage ( + activity () + .getString ( R.string.msg_confirm_delete, - String.format("%s [%s]", f.getName(), f.getAbsolutePath()))) - .setCancelable(false) - .create() - .show(); + String.format ("%s [%s]", f.getName (), f.getAbsolutePath ()))) + .setCancelable (false) + .create () + .show (); } - - private void renameFile(File f) { + + private void renameFile (File f) { final LayoutDialogTextInputBinding binding = - LayoutDialogTextInputBinding.inflate(LayoutInflater.from(activity())); - MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity()); - - Objects.requireNonNull(binding.name.getEditText()) - .setHint(activity().getString(R.string.new_name)); - binding.name.getEditText().setText(f.getName()); - - builder.setTitle(R.string.rename_file); - builder.setMessage(R.string.msg_rename_file); - builder.setView(binding.getRoot()); - builder.setNegativeButton(android.R.string.cancel, null); - builder.setPositiveButton( + LayoutDialogTextInputBinding.inflate (LayoutInflater.from (activity ())); + MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder (activity ()); + + Objects.requireNonNull (binding.name.getEditText ()) + .setHint (activity ().getString (R.string.new_name)); + binding.name.getEditText ().setText (f.getName ()); + + builder.setTitle (R.string.rename_file); + builder.setMessage (R.string.msg_rename_file); + builder.setView (binding.getRoot ()); + builder.setNegativeButton (android.R.string.cancel, null); + builder.setPositiveButton ( R.string.rename_file, (p1, p2) -> { - p1.dismiss(); - String name = binding.name.getEditText().getText().toString().trim(); + p1.dismiss (); + String name = binding.name.getEditText ().getText ().toString ().trim (); boolean renamed = - name.length() > 0 && name.length() <= 40 && FileUtils.rename(f, name); - activity() - .getApp() - .toast( + name.length () > 0 && name.length () <= 40 && FileUtils.rename (f, name); + activity () + .getApp () + .toast ( renamed ? R.string.renamed : R.string.rename_failed, renamed ? Toaster.Type.SUCCESS : Toaster.Type.ERROR); if (renamed) { // TODO Notify language servers about file rename event - if (activity().getLastHoldTreeNode() != null) { - TreeNode parent = activity().getLastHoldTreeNode().getParent(); - parent.deleteChild(activity().getLastHoldTreeNode()); - TreeNode node = new TreeNode(new File(f.getParentFile(), name)); - node.setViewHolder(new FileTreeViewHolder(activity())); - parent.addChild(node); - activity().getFileTreeFragment().expandNode(parent); + if (activity ().getLastHoldTreeNode () != null) { + TreeNode parent = activity ().getLastHoldTreeNode ().getParent (); + parent.deleteChild (activity ().getLastHoldTreeNode ()); + TreeNode node = new TreeNode (new File (f.getParentFile (), name)); + node.setViewHolder (new FileTreeViewHolder (activity ())); + parent.addChild (node); + activity ().getFileTreeFragment ().expandNode (parent); } else { - activity().getFileTreeFragment().listProjectFiles(); + activity ().getFileTreeFragment ().listProjectFiles (); } } }); - builder.create().show(); + builder.create ().show (); } } diff --git a/app/src/main/java/com/itsaky/androidide/handlers/IDEHandler.java b/app/src/main/java/com/itsaky/androidide/handlers/IDEHandler.java index 2f1bb80f2..7edd76d2d 100755 --- a/app/src/main/java/com/itsaky/androidide/handlers/IDEHandler.java +++ b/app/src/main/java/com/itsaky/androidide/handlers/IDEHandler.java @@ -36,10 +36,6 @@ public abstract class IDEHandler { this.provider = provider; } - protected void throwNPE() { - throw new NullPointerException(); - } - protected EditorActivity activity() { return provider.provideEditorActivity(); } diff --git a/app/src/main/res/layout/layout_boolean_attr_editor.xml b/app/src/main/res/layout/layout_boolean_attr_editor.xml new file mode 100644 index 000000000..e1554bb00 --- /dev/null +++ b/app/src/main/res/layout/layout_boolean_attr_editor.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_dimension_attr_editor.xml b/app/src/main/res/layout/layout_dimension_attr_editor.xml index 2357578b4..864d68173 100644 --- a/app/src/main/res/layout/layout_dimension_attr_editor.xml +++ b/app/src/main/res/layout/layout_dimension_attr_editor.xml @@ -14,8 +14,7 @@ ~ You should have received a copy of the GNU General Public License ~ along with AndroidIDE. If not, see . --> - IDE_PROPS = new HashMap<>(); - public static final Map ENV_VARS = new HashMap<>(); + + public static final Map IDE_PROPS = new HashMap<> (); + public static final Map ENV_VARS = new HashMap<> (); public static final String PROJECTS_FOLDER = "AndroidIDEProjects"; private static final String DEFAULT_JAVA_HOME = "/data/data/com.itsaky.androidide/files/framework/jdk"; private static final String DEFAULT_ANDROID_HOME = "/data/data/com.itsaky.androidide/files/framework/android-sdk"; - private static final Logger LOG = Logger.instance("Environment"); - private static final List blacklist = new ArrayList<>(); + private static final Logger LOG = Logger.instance ("Environment"); + private static final List blacklist = new ArrayList<> (); public static File ROOT; public static File SYSROOT; public static File HOME; @@ -63,7 +63,7 @@ public final class Environment { * contains only the classes included in android.jar */ public static File COMPILER_MODULE; - + public static File INIT_SCRIPT; public static File PROJECT_DATA_FILE; public static File GRADLE_PROPS; @@ -73,196 +73,193 @@ public final class Environment { public static File SHELL; public static File LOGIN_SHELL; public static File BOOTCLASSPATH; - - public static void init() { - final BaseApplication app = BaseApplication.getBaseInstance(); - ROOT = app.getIDEDataDir(); - SYSROOT = mkdirIfNotExits(new File(app.getIDEDataDir(), "sysroot")); - HOME = mkdirIfNotExits(app.getRootDir()); - ANDROIDIDE_HOME = mkdirIfNotExits(new File(HOME, ".androidide")); - TMP_DIR = mkdirIfNotExits(new File(SYSROOT, "tmp")); - BIN_DIR = mkdirIfNotExits(new File(SYSROOT, "bin")); - LIB_DIR = mkdirIfNotExits(new File(SYSROOT, "lib")); - PROJECTS_DIR = mkdirIfNotExits(new File(FileUtil.getExternalStorageDir(), PROJECTS_FOLDER)); - COMPILER_MODULE = mkdirIfNotExits(new File(ANDROIDIDE_HOME, "compiler-module")); - - IDE_PROPS_FILE = new File(SYSROOT, "etc/ide-environment.properties"); - LIB_HOOK = new File(LIB_DIR, "libhook.so"); - LIB_HOOK2 = new File(LIB_DIR, "libhook2.so"); - PROJECT_DATA_FILE = new File(TMP_DIR, "ide_project"); - + + public static void init () { + final BaseApplication app = BaseApplication.getBaseInstance (); + ROOT = app.getIDEDataDir (); + SYSROOT = mkdirIfNotExits (new File (app.getIDEDataDir (), "sysroot")); + HOME = mkdirIfNotExits (app.getRootDir ()); + ANDROIDIDE_HOME = mkdirIfNotExits (new File (HOME, ".androidide")); + TMP_DIR = mkdirIfNotExits (new File (SYSROOT, "tmp")); + BIN_DIR = mkdirIfNotExits (new File (SYSROOT, "bin")); + LIB_DIR = mkdirIfNotExits (new File (SYSROOT, "lib")); + PROJECTS_DIR = mkdirIfNotExits (new File (FileUtil.getExternalStorageDir (), PROJECTS_FOLDER)); + COMPILER_MODULE = mkdirIfNotExits (new File (ANDROIDIDE_HOME, "compiler-module")); + + IDE_PROPS_FILE = new File (SYSROOT, "etc/ide-environment.properties"); + LIB_HOOK = new File (LIB_DIR, "libhook.so"); + LIB_HOOK2 = new File (LIB_DIR, "libhook2.so"); + PROJECT_DATA_FILE = new File (TMP_DIR, "ide_project"); + INIT_SCRIPT = - new File( - mkdirIfNotExits(new File(app.getIDEDataDir(), "init")), + new File ( + mkdirIfNotExits (new File (app.getIDEDataDir (), "init")), "data/common/androidide.init.gradle"); - BOOTCLASSPATH = new File(""); - GRADLE_USER_HOME = new File(HOME, ".gradle"); - GRADLE_PROPS = new File(GRADLE_USER_HOME, "gradle.properties"); - - IDE_PROPS.putAll(readProperties()); - ANDROID_HOME = new File(readProp("ANDROID_HOME", DEFAULT_ANDROID_HOME)); - JAVA_HOME = new File(readProp("JAVA_HOME", DEFAULT_JAVA_HOME)); - - JAVA = new File(JAVA_HOME, "bin/java"); - BUSYBOX = new File(BIN_DIR, "busybox"); - SHELL = new File(BIN_DIR, "bash"); - LOGIN_SHELL = new File(BIN_DIR, "login"); - - setExecutable(JAVA); - setExecutable(BUSYBOX); - setExecutable(SHELL); - - System.setProperty("user.home", HOME.getAbsolutePath()); - System.setProperty("java.home", JAVA_HOME.getAbsolutePath()); + BOOTCLASSPATH = new File (""); + GRADLE_USER_HOME = new File (HOME, ".gradle"); + GRADLE_PROPS = new File (GRADLE_USER_HOME, "gradle.properties"); + + IDE_PROPS.putAll (readProperties ()); + ANDROID_HOME = new File (readProp ("ANDROID_HOME", DEFAULT_ANDROID_HOME)); + JAVA_HOME = new File (readProp ("JAVA_HOME", DEFAULT_JAVA_HOME)); + + JAVA = new File (JAVA_HOME, "bin/java"); + BUSYBOX = new File (BIN_DIR, "busybox"); + SHELL = new File (BIN_DIR, "bash"); + LOGIN_SHELL = new File (BIN_DIR, "login"); + + setExecutable (JAVA); + setExecutable (BUSYBOX); + setExecutable (SHELL); + + System.setProperty ("user.home", HOME.getAbsolutePath ()); + System.setProperty ("java.home", JAVA_HOME.getAbsolutePath ()); } - - public static void setExecutable(@NonNull final File file) { - if (!file.setExecutable(true)) { - LOG.error("Unable to set executable permissions to file", file); + + public static void setExecutable (@NonNull final File file) { + if (!file.setExecutable (true)) { + LOG.error ("Unable to set executable permissions to file", file); } } - + @NonNull - private static Map readProperties() { - final Map props = new HashMap<>(); - if (IDE_PROPS_FILE == null || !IDE_PROPS_FILE.exists()) { + private static Map readProperties () { + final Map props = new HashMap<> (); + if (IDE_PROPS_FILE == null || !IDE_PROPS_FILE.exists ()) { return props; } try { - Properties p = new Properties(); - p.load(new StringReader(FileIOUtils.readFile2String(IDE_PROPS_FILE))); - for (@SuppressWarnings("rawtypes") Map.Entry entry : p.entrySet()) { - props.put(entry.getKey() + "", entry.getValue() + ""); + Properties p = new Properties (); + p.load (new StringReader (FileIOUtils.readFile2String (IDE_PROPS_FILE))); + for (@SuppressWarnings("rawtypes") Map.Entry entry : p.entrySet ()) { + props.put (entry.getKey () + "", entry.getValue () + ""); } } catch (Throwable th) { - LOG.error("Unable to read properties file", th); + LOG.error ("Unable to read properties file", th); } return props; } - - public static void setBootClasspath(@NonNull File file) { - BOOTCLASSPATH = new File(file.getAbsolutePath()); + + public static void setBootClasspath (@NonNull File file) { + BOOTCLASSPATH = new File (file.getAbsolutePath ()); } - - public static Map getEnvironment() { - - if (!ENV_VARS.isEmpty()) { + + public static Map getEnvironment () { + + if (!ENV_VARS.isEmpty ()) { return ENV_VARS; } - - ENV_VARS.put("HOME", HOME.getAbsolutePath()); - ENV_VARS.put("ANDROID_HOME", ANDROID_HOME.getAbsolutePath()); - ENV_VARS.put("JAVA_HOME", JAVA_HOME.getAbsolutePath()); - ENV_VARS.put("GRADLE_USER_HOME", GRADLE_USER_HOME.getAbsolutePath()); - ENV_VARS.put("TMPDIR", TMP_DIR.getAbsolutePath()); - ENV_VARS.put("PROJECTS", PROJECTS_DIR.getAbsolutePath()); - ENV_VARS.put("LANG", "en_US.UTF-8"); - ENV_VARS.put("LC_ALL", "en_US.UTF-8"); - - ENV_VARS.put("SYSROOT", SYSROOT.getAbsolutePath()); - - ENV_VARS.put("BUSYBOX", BUSYBOX.getAbsolutePath()); - ENV_VARS.put("SHELL", SHELL.getAbsolutePath()); - ENV_VARS.put("CONFIG_SHELL", SHELL.getAbsolutePath()); - ENV_VARS.put("TERM", "screen"); - + + ENV_VARS.put ("HOME", HOME.getAbsolutePath ()); + ENV_VARS.put ("ANDROID_HOME", ANDROID_HOME.getAbsolutePath ()); + ENV_VARS.put ("JAVA_HOME", JAVA_HOME.getAbsolutePath ()); + ENV_VARS.put ("GRADLE_USER_HOME", GRADLE_USER_HOME.getAbsolutePath ()); + ENV_VARS.put ("TMPDIR", TMP_DIR.getAbsolutePath ()); + ENV_VARS.put ("PROJECTS", PROJECTS_DIR.getAbsolutePath ()); + ENV_VARS.put ("LANG", "en_US.UTF-8"); + ENV_VARS.put ("LC_ALL", "en_US.UTF-8"); + + ENV_VARS.put ("SYSROOT", SYSROOT.getAbsolutePath ()); + + ENV_VARS.put ("BUSYBOX", BUSYBOX.getAbsolutePath ()); + ENV_VARS.put ("SHELL", SHELL.getAbsolutePath ()); + ENV_VARS.put ("CONFIG_SHELL", SHELL.getAbsolutePath ()); + ENV_VARS.put ("TERM", "screen"); + // If LD_LIBRARY_PATH is set, append $SYSROOT/lib to it, // else set it to $SYSROOT/lib - String ld = System.getenv("LD_LIBRARY_PATH"); - if (ld == null || ld.trim().length() <= 0) { + String ld = System.getenv ("LD_LIBRARY_PATH"); + if (ld == null || ld.trim ().length () <= 0) { ld = ""; } else { ld += File.pathSeparator; } - ld += LIB_DIR.getAbsolutePath(); - ENV_VARS.put("LD_LIBRARY_PATH", ld); - + ld += LIB_DIR.getAbsolutePath (); + ENV_VARS.put ("LD_LIBRARY_PATH", ld); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R - && BaseApplication.isAarch64() - && LIB_HOOK.exists()) { + && BaseApplication.isAarch64 () + && LIB_HOOK.exists ()) { // Required for JDK 11 - ENV_VARS.put("LD_PRELOAD", LIB_HOOK.getAbsolutePath()); + ENV_VARS.put ("LD_PRELOAD", LIB_HOOK.getAbsolutePath ()); } - - addToEnvIfPresent(ENV_VARS, "ANDROID_ART_ROOT"); - addToEnvIfPresent(ENV_VARS, "DEX2OATBOOTCLASSPATH"); - addToEnvIfPresent(ENV_VARS, "ANDROID_I18N_ROOT"); - addToEnvIfPresent(ENV_VARS, "ANDROID_RUNTIME_ROOT"); - addToEnvIfPresent(ENV_VARS, "ANDROID_TZDATA_ROOT"); - addToEnvIfPresent(ENV_VARS, "ANDROID_DATA"); - addToEnvIfPresent(ENV_VARS, "ANDROID_ROOT"); - - String path = createPath(); - - ENV_VARS.put("PATH", path); - - for (String key : IDE_PROPS.keySet()) { - if (!blacklistedVariables().contains(key.trim())) { - ENV_VARS.put(key, readProp(key, "")); + + addToEnvIfPresent (ENV_VARS, "ANDROID_ART_ROOT"); + addToEnvIfPresent (ENV_VARS, "DEX2OATBOOTCLASSPATH"); + addToEnvIfPresent (ENV_VARS, "ANDROID_I18N_ROOT"); + addToEnvIfPresent (ENV_VARS, "ANDROID_RUNTIME_ROOT"); + addToEnvIfPresent (ENV_VARS, "ANDROID_TZDATA_ROOT"); + addToEnvIfPresent (ENV_VARS, "ANDROID_DATA"); + addToEnvIfPresent (ENV_VARS, "ANDROID_ROOT"); + + String path = createPath (); + + ENV_VARS.put ("PATH", path); + + for (String key : IDE_PROPS.keySet ()) { + if (!blacklistedVariables ().contains (key.trim ())) { + ENV_VARS.put (key, readProp (key, "")); } } - + return ENV_VARS; } - + @NonNull - private static String createPath() { + private static String createPath () { String path = ""; - path += String.format("%s/bin", JAVA_HOME.getAbsolutePath()); - path += String.format(":%s/cmdline-tools/latest/bin", ANDROID_HOME.getAbsolutePath()); - path += String.format(":%s/cmake/bin", ANDROID_HOME.getAbsolutePath()); - path += String.format(":%s/bin", SYSROOT.getAbsolutePath()); - path += String.format(":%s", System.getenv("PATH")); + path += String.format ("%s/bin", JAVA_HOME.getAbsolutePath ()); + path += String.format (":%s/cmdline-tools/latest/bin", ANDROID_HOME.getAbsolutePath ()); + path += String.format (":%s/cmake/bin", ANDROID_HOME.getAbsolutePath ()); + path += String.format (":%s/bin", SYSROOT.getAbsolutePath ()); + path += String.format (":%s", System.getenv ("PATH")); return path; } - - public static void addToEnvIfPresent(Map environment, String name) { - String value = System.getenv(name); + + public static void addToEnvIfPresent (Map environment, String name) { + String value = System.getenv (name); if (value != null) { - environment.put(name, value); + environment.put (name, value); } } - - public static String readPropOrNull(String key) { - return readProp(key, null); - } - - public static String readProp(String key, String defaultValue) { - String value = IDE_PROPS.getOrDefault(key, defaultValue); + + public static String readProp (String key, String defaultValue) { + String value = IDE_PROPS.getOrDefault (key, defaultValue); if (value == null) { return defaultValue; } - if (value.contains("$HOME")) { - value = value.replace("$HOME", HOME.getAbsolutePath()); + if (value.contains ("$HOME")) { + value = value.replace ("$HOME", HOME.getAbsolutePath ()); } - if (value.contains("$SYSROOT")) { - value = value.replace("$SYSROOT", SYSROOT.getAbsolutePath()); + if (value.contains ("$SYSROOT")) { + value = value.replace ("$SYSROOT", SYSROOT.getAbsolutePath ()); } - if (value.contains("$PATH")) { - value = value.replace("$PATH", createPath()); + if (value.contains ("$PATH")) { + value = value.replace ("$PATH", createPath ()); } return value; } - - public static File mkdirIfNotExits(File in) { - if (in != null && !in.exists()) { - FileUtils.createOrExistsDir(in); + + public static File mkdirIfNotExits (File in) { + if (in != null && !in.exists ()) { + FileUtils.createOrExistsDir (in); } - + return in; } - - public static boolean isCompilerModuleInstalled() { - final var modules = new File(COMPILER_MODULE, "lib/modules"); - final var release = new File(COMPILER_MODULE, "release"); - return modules.exists() && modules.isFile() && release.exists() && release.isFile(); + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public static boolean isCompilerModuleInstalled () { + final var modules = new File (COMPILER_MODULE, "lib/modules"); + final var release = new File (COMPILER_MODULE, "release"); + return modules.exists () && modules.isFile () && release.exists () && release.isFile (); } - - private static List blacklistedVariables() { - if (blacklist.isEmpty()) { - blacklist.add("HOME"); - blacklist.add("SYSROOT"); - blacklist.add("JLS_HOME"); + + private static List blacklistedVariables () { + if (blacklist.isEmpty ()) { + blacklist.add ("HOME"); + blacklist.add ("SYSROOT"); + blacklist.add ("JLS_HOME"); } return blacklist; } diff --git a/common/src/main/java/com/itsaky/androidide/utils/Logger.java b/common/src/main/java/com/itsaky/androidide/utils/Logger.java index 819155fca..0e7b998f4 100755 --- a/common/src/main/java/com/itsaky/androidide/utils/Logger.java +++ b/common/src/main/java/com/itsaky/androidide/utils/Logger.java @@ -120,12 +120,12 @@ public class Logger { } for (Object msg : messages) { - sb.append("\n"); + sb.append(msg instanceof Throwable ? "\n" : MSG_SEPARATOR); sb.append( msg instanceof Throwable ? ThrowableUtils.getFullStackTrace(((Throwable) msg)) : msg); - sb.append("\n"); + sb.append(msg instanceof Throwable ? "\n" : MSG_SEPARATOR); } return sb.toString(); diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 3ae7400fb..bea934b15 100755 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -31,4 +31,8 @@ ext { gson: 'com.google.code.gson:gson:2.8.8', guava: 'com.google.guava:guava:30.1.1-android' ] + + tests = [ + junit4: 'junit:junit:4.13' + ] } \ No newline at end of file diff --git a/xml-inflater/build.gradle b/xml-inflater/build.gradle index a5e2e5f8e..56df0dab8 100644 --- a/xml-inflater/build.gradle +++ b/xml-inflater/build.gradle @@ -35,4 +35,6 @@ dependencies { implementation project (":common") api project (':sdk-info') + + testImplementation tests.junit4 } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java new file mode 100644 index 000000000..f379742cb --- /dev/null +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java @@ -0,0 +1,68 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.inflater.values; + +import static java.lang.reflect.Modifier.isPublic; +import static java.lang.reflect.Modifier.isStatic; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Provides framework resource values. + * + * @author Akash Yadav + */ +public class FrameworkValues { + + @NonNull + public static List listDimens () { + return listFields (android.R.dimen.class); + } + + @NonNull + public static List listStrings () { + return listFields (android.R.string.class); + } + + @NonNull + public static List listColors () { + return listFields (android.R.color.class); + } + + @NonNull + private static List listFields (final Class klass) { + Objects.requireNonNull (klass); + + final var list = new ArrayList (); + final var fields = klass.getDeclaredFields (); + for (var field : fields) { + final var mods = field.getModifiers (); + if (!isPublic (mods) || !isStatic (mods)) { + continue; + } + + list.add (field.getName ()); + } + + return list; + } +} diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java index 7bc2b909d..0196b6b90 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java @@ -48,8 +48,8 @@ import java.util.Objects; * @author Akash Yadav */ public class ValuesTable { - - private static final Logger LOG = Logger.instance("ValuesTable"); + + private static final Logger LOG = Logger.instance ("ValuesTable"); // TODO Parse styles and styleables private final Map arrays; private final Map strings; @@ -57,185 +57,185 @@ public class ValuesTable { private final Map integers; private final Map dimens; private final Map booleans; - - private final Map> resourceMap = new HashMap<>(); - - private ValuesTable() { - this.arrays = new HashMap<>(); - this.strings = new HashMap<>(); - this.colors = new HashMap<>(); - this.integers = new HashMap<>(); - this.dimens = new HashMap<>(); - this.booleans = new HashMap<>(); - - this.resourceMap.put("array", this.arrays); - this.resourceMap.put("string", this.strings); - this.resourceMap.put("color", this.colors); - this.resourceMap.put("integer", this.integers); - this.resourceMap.put("dimen", this.dimens); - this.resourceMap.put("bool", this.booleans); + + private final Map> resourceMap = new HashMap<> (); + + protected ValuesTable () { + this.arrays = new HashMap<> (); + this.strings = new HashMap<> (); + this.colors = new HashMap<> (); + this.integers = new HashMap<> (); + this.dimens = new HashMap<> (); + this.booleans = new HashMap<> (); + + this.resourceMap.put ("array", this.arrays); + this.resourceMap.put ("string", this.strings); + this.resourceMap.put ("color", this.colors); + this.resourceMap.put ("integer", this.integers); + this.resourceMap.put ("dimen", this.dimens); + this.resourceMap.put ("bool", this.booleans); } - + /** * Create a new table by reading the files from the given values directory. * * @param valuesDirectory The "res/values" directory. * @return The values table or {@code null} if the directory is invalid or there are no files in - * this directory. + * this directory. * @throws XmlPullParserException Thrown by {@link XmlPullParserFactory}. - * @throws IOException Thrown by {@link XmlPullParser}. + * @throws IOException Thrown by {@link XmlPullParser}. */ @Nullable - public static ValuesTable forDirectory(File valuesDirectory) throws Exception { + public static ValuesTable forDirectory (File valuesDirectory) throws Exception { if (valuesDirectory == null) { - LOG.error("Cannot create values table for directory: ", null); + LOG.error ("Cannot create values table for directory: ", null); return null; } - - if (!valuesDirectory.exists()) { - LOG.error( + + if (!valuesDirectory.exists ()) { + LOG.error ( "Cannot create values table for directory as it does not exists. Directory:", valuesDirectory); return null; } - - final var files = valuesDirectory.listFiles(ValuesTable::isValid); + + final var files = valuesDirectory.listFiles (ValuesTable::isValid); if (files == null) { - LOG.error("No files found in the given values directory"); + LOG.error ("No files found in the given values directory"); return null; } - - final var start = System.currentTimeMillis(); - final var values = new ValuesTable(); - + + final var start = System.currentTimeMillis (); + final var values = new ValuesTable (); + for (var file : files) { - final var factory = XmlPullParserFactory.newInstance(); - final var parser = factory.newPullParser(); - parser.setInput(new FileInputStream(file), null); - - var event = parser.getEventType(); + final var factory = XmlPullParserFactory.newInstance (); + final var parser = factory.newPullParser (); + parser.setInput (new FileInputStream (file), null); + + var event = parser.getEventType (); while (event != XmlPullParser.END_DOCUMENT) { if (event == XmlPullParser.START_TAG) { - final var tag = parser.getName(); - if ("resources".equals(tag)) { - event = parser.next(); + final var tag = parser.getName (); + if ("resources".equals (tag)) { + event = parser.next (); continue; } - - readTag(tag, parser, values); + + readTag (tag, parser, values); } - event = parser.next(); + event = parser.next (); } } - - final var duration = System.currentTimeMillis() - start; - LOG.info( - String.format( - Locale.getDefault(), + + final var duration = System.currentTimeMillis () - start; + LOG.info ( + String.format ( + Locale.getDefault (), "Took %d ms to read %d files in directory: %s", duration, files.length, valuesDirectory)); - + return values; } - - private static void readTag(String tag, XmlPullParser parser, ValuesTable values) + + private static void readTag (String tag, XmlPullParser parser, ValuesTable values) throws Exception { - - if ("style".equals(tag) || "declare-styleable".equals(tag)) { + + if ("style".equals (tag) || "declare-styleable".equals (tag)) { // These tags are not supported yet // Skip parsing until we reach next tag with same depth as of this tag - skip(parser); + skip (parser); return; } - + // TODO Should we check if these tags are specified within ? - final var name = getName(parser); + final var name = getName (parser); if (name == null) { - LOG.error(String.format("A <%s> resource was found with no 'name' attribute", tag)); + LOG.error (String.format ("A <%s> resource was found with no 'name' attribute", tag)); return; } - - if ("item".equals(tag)) { - tag = parser.getAttributeValue(null, "type"); + + if ("item".equals (tag)) { + tag = parser.getAttributeValue (null, "type"); if (tag == null) { - LOG.error(" resource value found but no 'type' was specified."); + LOG.error (" resource value found but no 'type' was specified."); return; } } - + // check for array before reading value // because array resources do not have text values - if ("array".equals(tag) || tag.endsWith("-array")) { - readArray(parser, values, name); + if ("array".equals (tag) || tag.endsWith ("-array")) { + readArray (parser, values, name); return; } - + // Value must be read after all other required values have been read - final var value = parser.nextText(); + final var value = parser.nextText (); IResource resourceValue; - + switch (tag) { case "string": resourceValue = new StringResource (name, value); - values.strings.put(name, resourceValue); + values.strings.put (name, resourceValue); break; case "color": resourceValue = new ColorResource (name, value); - values.colors.put(name, resourceValue); + values.colors.put (name, resourceValue); break; case "bool": resourceValue = new BooleanResource (name, value); - values.booleans.put(name, resourceValue); + values.booleans.put (name, resourceValue); break; case "dimen": resourceValue = new DimensionResource (name, value); - values.dimens.put(name, resourceValue); + values.dimens.put (name, resourceValue); break; case "integer": resourceValue = new IntegerResource (name, value); - values.integers.put(name, resourceValue); + values.integers.put (name, resourceValue); break; default: - LOG.warn("Unknown or unsupported resource value tag:", tag); + LOG.warn ("Unknown or unsupported resource value tag:", tag); break; } } - - private static void readArray(@NonNull XmlPullParser parser, ValuesTable values, String name) + + private static void readArray (@NonNull XmlPullParser parser, ValuesTable values, String name) throws XmlPullParserException, IOException { - final var minDepth = parser.getDepth(); - final var items = new ArrayList(); - - var event = parser.getEventType(); - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT - && parser.getDepth() >= minDepth) { + final var minDepth = parser.getDepth (); + final var items = new ArrayList (); + + var event = parser.getEventType (); + while ((event = parser.next ()) != XmlPullParser.END_DOCUMENT + && parser.getDepth () >= minDepth) { if (event == XmlPullParser.START_TAG) { - final var child = parser.getName(); - if ("item".equals(child)) { - final var value = parser.nextText(); - items.add(value); + final var child = parser.getName (); + if ("item".equals (child)) { + final var value = parser.nextText (); + items.add (value); } } } - - final var arr = new String[items.size()]; + + final var arr = new String[items.size ()]; for (int i = 0; i < arr.length; i++) { - arr[i] = items.get(i); + arr[i] = items.get (i); } - - values.arrays.put(name, new ArrayResource(name, arr)); + + values.arrays.put (name, new ArrayResource (name, arr)); } - - private static void skip(@NonNull XmlPullParser parser) + + private static void skip (@NonNull XmlPullParser parser) throws XmlPullParserException, IOException { - if (parser.getEventType() != XmlPullParser.START_TAG) { - throw new IllegalStateException(); + if (parser.getEventType () != XmlPullParser.START_TAG) { + throw new IllegalStateException (); } int depth = 1; while (depth != 0) { - switch (parser.next()) { + switch (parser.next ()) { case XmlPullParser.END_TAG: depth--; break; @@ -245,21 +245,21 @@ public class ValuesTable { } } } - - private static String getName(@NonNull XmlPullParser parser) { - return parser.getAttributeValue(null, "name"); + + private static String getName (@NonNull XmlPullParser parser) { + return parser.getAttributeValue (null, "name"); } - - private static boolean isValid(File file) { - return file != null && file.isFile() && FileUtils.isUtf8(file); + + private static boolean isValid (File file) { + return file != null && file.isFile () && FileUtils.isUtf8 (file); } - + @Nullable - public Map getTable(final String name) { - Objects.requireNonNull(name); - return this.resourceMap.get(name); + public Map getTable (final String name) { + Objects.requireNonNull (name); + return this.resourceMap.get (name); } - + /** * Finds a resource value of any type. * @@ -267,133 +267,133 @@ public class ValuesTable { * @return The resource value or {@code null} if there is no resource with the given name. */ @SuppressWarnings("unused") - public IResource findResource(final String name) { + public IResource findResource (final String name) { IResource value; - - value = findString(name); + + value = findString (name); if (value != null) { return value; } - - value = findColor(name); + + value = findColor (name); if (value != null) { return value; } - - value = findInteger(name); + + value = findInteger (name); if (value != null) { return value; } - - value = findDimension(name); + + value = findDimension (name); if (value != null) { return value; } - - value = findArray(name); + + value = findArray (name); if (value != null) { return value; } - - value = findBoolean(name); + + value = findBoolean (name); //noinspection RedundantIfStatement if (value != null) { return value; } - + return null; } - - public ArrayResource findArray(final String name) { - return (ArrayResource) arrays.getOrDefault(name, null); + + public ArrayResource findArray (final String name) { + return (ArrayResource) arrays.getOrDefault (name, null); } - + /** * Find a string value with the given name. * * @param name The name of the string resource. * @return The string resource or {@code null} if there is no resource with the given name. */ - public StringResource findString(final String name) { - return (StringResource) strings.getOrDefault(name, null); + public StringResource findString (final String name) { + return (StringResource) strings.getOrDefault (name, null); } - + /** * Find a color value with the given name. * * @param name The name of the color resource. * @return The color resource or {@code null} if there is no resource with the given name. */ - public ColorResource findColor(final String name) { - return (ColorResource) colors.getOrDefault(name, null); + public ColorResource findColor (final String name) { + return (ColorResource) colors.getOrDefault (name, null); } - + /** * Find a integer value with the given name. * * @param name The name of the integer resource. * @return The integer resource or {@code null} if there is no resource with the given name. */ - public IntegerResource findInteger(final String name) { - return (IntegerResource) integers.getOrDefault(name, null); + public IntegerResource findInteger (final String name) { + return (IntegerResource) integers.getOrDefault (name, null); } - + /** * Find a dimension value with the given name. * * @param name The name of the dimension resource. * @return The dimension resource or {@code null} if there is no resource with the given name. */ - public DimensionResource findDimension(final String name) { - return (DimensionResource) dimens.getOrDefault(name, null); + public DimensionResource findDimension (final String name) { + return (DimensionResource) dimens.getOrDefault (name, null); } - + /** * Find a boolean value with the given name. * * @param name The name of the boolean resource. * @return The boolean resource or {@code null} if there is no resource with the given name. */ - public BooleanResource findBoolean(final String name) { - return (BooleanResource) booleans.getOrDefault(name, null); + public BooleanResource findBoolean (final String name) { + return (BooleanResource) booleans.getOrDefault (name, null); } - + /** * Reads the contents of the given file and updates this table. * * @param file The file to sync with. */ - public void syncWithFile(final File file) throws Exception { - final var start = System.currentTimeMillis(); - final var factory = XmlPullParserFactory.newInstance(); - final var parser = factory.newPullParser(); - parser.setInput(new FileInputStream(file), null); - - var event = parser.getEventType(); + public void syncWithFile (final File file) throws Exception { + final var start = System.currentTimeMillis (); + final var factory = XmlPullParserFactory.newInstance (); + final var parser = factory.newPullParser (); + parser.setInput (new FileInputStream (file), null); + + var event = parser.getEventType (); while (event != XmlPullParser.END_DOCUMENT) { if (event == XmlPullParser.START_TAG) { - final var tag = parser.getName(); - if ("resources".equals(tag)) { - event = parser.next(); + final var tag = parser.getName (); + if ("resources".equals (tag)) { + event = parser.next (); continue; } - - ValuesTable.readTag(tag, parser, this); + + ValuesTable.readTag (tag, parser, this); } - event = parser.next(); + event = parser.next (); } - - LOG.debug( + + LOG.debug ( "Syncing with file", - file.getName(), + file.getName (), "took", - (System.currentTimeMillis() - start), + (System.currentTimeMillis () - start), "ms"); } - + @NonNull @Override - public String toString() { + public String toString () { return "ValuesTable{" + "strings=" + strings diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java index ac5b7246b..f25cc4c0c 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java @@ -31,109 +31,110 @@ import java.util.regex.Pattern; * @author Akash Yadav */ public class ValuesTableFactory { - - private static final Map valueTables = new HashMap<>(); - private static final Logger LOG = Logger.instance("ValuesTableFactory"); - - public static ValuesTable getTable(final File resDir) { - return valueTables.getOrDefault(resDir, null); + + private static final Map valueTables = new HashMap<> (); + private static final Logger LOG = Logger.instance ("ValuesTableFactory"); + + public static ValuesTable getTable (final File resDir) { + return valueTables.getOrDefault (resDir, null); } - - public static Map getAllTables() { + + public static Map getAllTables () { return valueTables; } - + /** * Setup this ValuesTableFactory with the given "res" directories. * * @param resDirs The resource directories. */ - public static void setupWithResDirectories(File... resDirs) { - + public static void setupWithResDirectories (File... resDirs) { + if (resDirs == null || resDirs.length <= 0) { - LOG.error("Cannot create value tables. No directories were specified."); + LOG.error ("Cannot create value tables. No directories were specified."); return; } - - valueTables.clear(); - - final var start = System.currentTimeMillis(); + + valueTables.clear (); + + final var start = System.currentTimeMillis (); for (var res : resDirs) { - if (res == null || !res.exists()) { + if (res == null || !res.exists ()) { continue; } - - final var table = createTable(res); + + final var table = createTable (res); if (table == null) { continue; } - - valueTables.put(res, table); + + valueTables.put (res, table); } - - LOG.debug( - String.format( - Locale.getDefault(), + + LOG.debug ( + String.format ( + Locale.getDefault (), "Created value tables for %d resource directories in %d ms", resDirs.length, - (System.currentTimeMillis() - start))); + (System.currentTimeMillis () - start))); } - + /** * Notify that the given file's contents were changed and the corresponding table must be * updated with new values. * * @param file The file that was changed. */ - public static void syncWithFile(final File file) { + public static void syncWithFile (final File file) { if (file == null) { - LOG.error("Cannot update value tables. Given file is null."); + LOG.error ("Cannot update value tables. Given file is null."); return; } - - final var pattern = Pattern.compile(".*/src/.*/res/values/(\\w|_)+\\.xml"); - if (!pattern.matcher(file.getAbsolutePath()).matches()) { + + final var pattern = Pattern.compile (".*/src/.*/res/values/(\\w|_)+\\.xml"); + if (!pattern.matcher (file.getAbsolutePath ()).matches ()) { // This file is not a values resource file. return; } - + final var resDir = - Objects.requireNonNull(file.getParentFile()) /* values dir */ - .getParentFile() /* res dir*/; - var table = valueTables.getOrDefault(resDir, null); + Objects.requireNonNull (file.getParentFile ()) /* values dir */ + .getParentFile () /* res dir*/; + var table = valueTables.getOrDefault (resDir, null); if (table == null) { - table = createTable(resDir); + table = createTable (resDir); if (table != null) { - valueTables.put(resDir, table); + valueTables.put (resDir, table); } return; } - + try { - table.syncWithFile(file); + table.syncWithFile (file); } catch (Throwable e) { - LOG.error("Failed to sync values table", e); + LOG.error ("Failed to sync values table", e); } } - - private static ValuesTable createTable(File res) { + + private static ValuesTable createTable (File res) { try { - final var values = new File(res, "values"); - if (!values.exists()) { + final var values = new File (res, "values"); + if (!values.exists ()) { return null; } - - var table = ValuesTable.forDirectory(values); + + var table = ValuesTable.forDirectory (values); if (table == null) { - throw new ParseException(); + throw new ParseException (); } - + return table; } catch (Throwable e) { - LOG.error("Failed to create values table", e); + LOG.error ("Failed to create values table", e); return null; } } - - static class ParseException extends RuntimeException {} + + static class ParseException extends RuntimeException { + } } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java index 85bb32e32..79906ee24 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java @@ -28,31 +28,31 @@ import java.util.Objects; * @author Akash Yadav */ abstract class AbstractResource implements IResource { - + private final String name; private final String value; - - public AbstractResource (@NonNull String name, @NonNull String value) { + + public AbstractResource(@NonNull String name, @NonNull String value) { this.name = name; this.value = value; } - + @NonNull @Override - public String getName () { + public String getName() { return name; } - + @NonNull @Override - public String getValue () { + public String getValue() { return value; } - + @NonNull @Override - public String toString () { - return getClass ().getSimpleName () + public String toString() { + return getClass().getSimpleName() + "{" + "name='" + name @@ -62,24 +62,24 @@ abstract class AbstractResource implements IResource { + '\'' + '}'; } - + @Override - public boolean equals (Object o) { + public boolean equals(Object o) { if (this == o) { return true; } - + if (!(o instanceof AbstractResource)) { return false; } - + AbstractResource that = (AbstractResource) o; - return Objects.equals (getName (), that.getName ()) - && Objects.equals (getValue (), that.getValue ()); + return Objects.equals(getName(), that.getName()) + && Objects.equals(getValue(), that.getValue()); } - + @Override - public int hashCode () { - return Objects.hash (getName (), getValue ()); + public int hashCode() { + return Objects.hash(getName(), getValue()); } } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java index ced6c97ea..72c5761f1 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java @@ -19,12 +19,10 @@ package com.itsaky.inflater.values.models; import androidx.annotation.NonNull; -/** - * @author Akash Yadav - */ +/** @author Akash Yadav */ public class BooleanResource extends AbstractResource { - public BooleanResource (@NonNull String name, @NonNull String value) { + public BooleanResource(@NonNull String name, @NonNull String value) { super(name, value); } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java index 691148d14..bc12d398d 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java @@ -27,7 +27,7 @@ import androidx.annotation.NonNull; */ public class ColorResource extends AbstractResource { - public ColorResource (@NonNull String name, @NonNull String value) { + public ColorResource(@NonNull String name, @NonNull String value) { super(name, value); } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java index 9c75e10d5..23a39d2ca 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java @@ -25,7 +25,7 @@ import androidx.annotation.NonNull; */ public class DimensionResource extends AbstractResource { - public DimensionResource (@NonNull String name, @NonNull String value) { + public DimensionResource(@NonNull String name, @NonNull String value) { super(name, value); } } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java index 3d261cd41..edadf5e3c 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java @@ -25,7 +25,7 @@ import androidx.annotation.NonNull; */ public class IntegerResource extends AbstractResource { - public IntegerResource (@NonNull String name, @NonNull String value) { + public IntegerResource(@NonNull String name, @NonNull String value) { super(name, value); } diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java index 2797c2ff6..8a16a6faa 100644 --- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java +++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java @@ -25,7 +25,7 @@ import androidx.annotation.NonNull; */ public class StringResource extends AbstractResource { - public StringResource (@NonNull String name, @NonNull String value) { + public StringResource(@NonNull String name, @NonNull String value) { super(name, value); } }