Initial commit

This commit is contained in:
2023-09-03 01:11:35 +08:00
commit 416f05460e
164 changed files with 12089 additions and 0 deletions

17
.editorconfig Normal file
View File

@@ -0,0 +1,17 @@
# noinspection EditorConfigKeyCorrectness
[{*.kt,*.kts}]
ktlint_standard_annotation = disabled
ktlint_standard_filename = disabled
ktlint_standard_wrapping = disabled
ktlint_standard_import-ordering = enabled
ktlint_standard_max-line-length = disabled
ktlint_standard_multiline-if-else = disabled
ktlint_standard_argument-list-wrapping = disabled
ktlint_standard_parameter-list-wrapping = disabled
ktlint_standard_trailing-comma-on-declaration-site = disabled
ktlint_function_signature_body_expression_wrapping = multiline
ij_continuation_indent_size = 2
indent_size = 4
indent_style = space
insert_final_newline = false
max_line_length = 150

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
*.iml
.gradle
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
/gradle.xml
/misc.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

12
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17">
<module name="SweetDependency.buildSrc" target="17" />
<module name="SweetDependency.buildSrc.main" target="17" />
<module name="SweetDependency.buildSrc.test" target="17" />
<module name="SweetDependency.main" target="17" />
<module name="SweetDependency.test" target="17" />
</bytecodeTargetLevel>
</component>
</project>

BIN
.idea/icon.png generated Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

View File

@@ -0,0 +1,14 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="HttpUrlsUsage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="UnstableApiUsage" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedVersionCatalogEntry" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

20
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

6
.idea/kotlinc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.10" />
</component>
</project>

6
.idea/ktlint.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KtlintProjectConfiguration">
<treatAsErrors>false</treatAsErrors>
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

202
LICENSE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright HighCapable [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

93
README-zh-CN.md Normal file
View File

@@ -0,0 +1,93 @@
# Sweet Dependency
[![Blank](https://img.shields.io/badge/license-Apache2.0-blue)](https://github.com/HighCapable/SweetDependency/blob/master/LICENSE)
![Blank](https://img.shields.io/badge/version-v1.0.0-green)
[![Telegram](https://img.shields.io/badge/Discussion-Telegram-blue.svg?logo=telegram)](https://t.me/HighCapable_Dev)
<img src="https://github.com/HighCapable/SweetDependency/blob/master/img-src/icon.png?raw=true" width = "100" height = "100" alt="LOGO"/>
一个轻松自动装配和管理依赖的 Gradle 插件。
[English](https://github.com/HighCapable/SweetDependency/blob/master/README.md) | 简体中文
## 这是什么
这是一个用来管理 Gradle 依赖的 Gradle 插件,所有依赖集中管理并自动更新,解决了每个子项目都需要手动更新到相同版本依赖的问题。
虽然 Gradle 后期推出了 Version Catalogs 来管理依赖,但是它的方式依然不够自由和人性化,且存在限制。
不同于传统的依赖管理方式,`SweetDependency` 采用 YAML 进行动态配置,可读性相对较高,配置过程简单且易用。
## 兼容性
不仅仅是 Android 项目,任何使用 Gradle 作为构建工具的项目都可以使用。
目前暂时只有 Gradle 插件IDEA 的相关插件还在计划开发中,预计将会支持配置文件的语法检查和将配置文件显示在 Android 项目的 Gradle 文件列表中。
支持 Gradle `7.x.x``8.x.x`,其它版本未做测试并不推荐使用。
> 构建脚本语言
- Kotlin DSL
推荐优先使用此语言作为构建脚本语言,这也是目前 Gradle 推荐的语言。
- Groovy DSL
部分功能可能无法兼容,在后期会逐渐放弃支持,且部分功能会无法使用。
> 相关功能列表
部分功能将跟随后期用户需求逐渐完善。
- [x] 支持 Kotlin Multiplatform
- [x] 管理 Gradle 插件依赖
- [x] 管理 Gradle 库依赖
- [x] 自动装配 Maven 依赖 (POM、BOM)
- [ ] 自动装配 Ivy 依赖
## 开始使用
- [点击这里](https://github.com/HighCapable/SweetDependency/blob/master/docs/guide-zh-CN.md) 查看使用文档
## 更新日志
- [点击这里](https://github.com/HighCapable/SweetDependency/blob/master/docs/changelog-zh-CN.md) 查看历史更新日志
## 项目推广
如果你正在寻找一个可以自动生成属性键值的 Gradle 插件,你可以了解一下 [SweetProperty](https://github.com/HighCapable/SweetProperty) 项目。
本项目同样使用了 **SweetProperty**
## Star History
![Star History Chart](https://api.star-history.com/svg?repos=HighCapable/SweetDependency&type=Date)
## 许可证
- [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
```
Apache License Version 2.0
Copyright (C) 2019-2023 HighCapable
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
版权所有 © 2019-2023 HighCapable

96
README.md Normal file
View File

@@ -0,0 +1,96 @@
# Sweet Dependency
[![Blank](https://img.shields.io/badge/license-Apache2.0-blue)](https://github.com/HighCapable/SweetDependency/blob/master/LICENSE)
![Blank](https://img.shields.io/badge/version-v1.0.0-green)
[![Telegram](https://img.shields.io/badge/Discussion-Telegram-blue.svg?logo=telegram)](https://t.me/HighCapable_Dev)
<img src="https://github.com/HighCapable/SweetDependency/blob/master/img-src/icon.png?raw=true" width = "100" height = "100" alt="LOGO"/>
An easy autowire and manage dependencies Gradle plugin.
English | [简体中文](https://github.com/HighCapable/SweetDependency/blob/master/README-zh-CN.md)
## What's this
This is a Gradle plugin for managing Gradle dependencies.
Although Gradle later launched the Version Catalogs to manage dependencies, its method is still not free and user-friendly, and has limitations.
Different from traditional dependency management methods, `SweetDependency` uses YAML for dynamic configuration,
which is relatively readable, and the configuration process is simple and easy to use.
## Compatibility
Not just Android projects, any project that uses Gradle as a build tool will work.
Currently there is only Gradle plugin, IDEA related plugins are still under development,
support for syntax checking of configuration file and displaying configuration file in the Android project's Gradle files list is expected.
Gradle `7.x.x` and `8.x.x` are supported, other versions have not been tested and are not recommended.
> Build Script Language
- Kotlin DSL
It is recommended to use this language as the build script language first, which is also the language currently recommended by Gradle.
- Groovy DSL
Some functions may be incompatible, support will be gradually dropped in the future, and some functions may become unavailable.
> Related Feature List
Some functions will be gradually improved following the needs of users.
- [x] Support Kotlin Multiplatform
- [x] Manage Gradle dependencies (plugins)
- [x] Manage Gradle dependencies (libraries)
- [x] Autowire Maven dependencies (POM, BOM)
- [ ] Autowire Ivy dependencies
## Get Started
- [Click here](https://github.com/HighCapable/SweetDependency/blob/master/docs/guide.md) to view the documentation
## Changelog
- [Click here](https://github.com/HighCapable/SweetDependency/blob/master/docs/changelog.md) to view the historical changelog
## Promotion
If you are looking for a Gradle plugin that can automatically generate properties key-values,
you can check out the [SweetProperty](https://github.com/HighCapable/SweetProperty) project.
This project also uses **SweetProperty**.
## Star History
![Star History Chart](https://api.star-history.com/svg?repos=HighCapable/SweetDependency&type=Date)
## License
- [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
```
Apache License Version 2.0
Copyright (C) 2019-2023 HighCapable
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
Copyright © 2019-2023 HighCapable

16
build.gradle.kts Normal file
View File

@@ -0,0 +1,16 @@
plugins {
autowire(libs.plugins.kotlin.jvm) apply false
}
allprojects {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "17"
freeCompilerArgs = listOf(
"-Xno-param-assertions",
"-Xno-call-assertions",
"-Xno-receiver-assertions"
)
}
}
}

5
docs/changelog-zh-CN.md Normal file
View File

@@ -0,0 +1,5 @@
# 更新日志
## 1.0.0 | 2023.09.03
- 首个版本提交至 Maven

5
docs/changelog.md Normal file
View File

@@ -0,0 +1,5 @@
# Changelog
## 1.0.0 | 2023.09.03
- The first version is submitted to Maven

1156
docs/guide-zh-CN.md Normal file

File diff suppressed because it is too large Load Diff

1223
docs/guide.md Normal file

File diff suppressed because it is too large Load Diff

15
examples/sample-android/.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

View File

@@ -0,0 +1,5 @@
plugins {
autowire(libs.plugins.com.android.application) apply false
autowire(libs.plugins.com.android.library) apply false
autowire(libs.plugins.org.jetbrains.kotlin.android) apply false
}

View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,42 @@
plugins {
autowire(libs.plugins.com.android.application)
autowire(libs.plugins.org.jetbrains.kotlin.android)
}
android {
namespace = "com.highcapable.sweetdependency.demo_app"
compileSdk = 33
defaultConfig {
applicationId = "com.highcapable.sweetdependency.demo_app"
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
dependencies {
implementation(androidx.core.core.ktx)
implementation(androidx.appcompat.appcompat)
implementation(com.google.android.material.material)
implementation(androidx.constraintlayout.constraintlayout)
testImplementation(junit.junit)
androidTestImplementation(androidx.test.ext.junit)
androidTestImplementation(androidx.test.espresso.espresso.core)
}

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,24 @@
package com.highcapable.sweetdependency.demo_app
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.highcapable.sweetdependency.demo_app", appContext.packageName)
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.SweetDependency"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,12 @@
package com.highcapable.sweetdependency.demo_app
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}

View File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SweetDependency" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">SweetDependency</string>
</resources>

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SweetDependency" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@@ -0,0 +1,17 @@
package com.highcapable.sweetdependency.demo_app
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,40 @@
plugins {
autowire(libs.plugins.com.android.library)
autowire(libs.plugins.org.jetbrains.kotlin.android)
}
android {
namespace = "com.highcapable.sweetdependency.demo_library"
compileSdk = 33
defaultConfig {
minSdk = 24
targetSdk = 33
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
dependencies {
implementation(androidx.core.core.ktx)
implementation(androidx.appcompat.appcompat)
implementation(com.google.android.material.material)
implementation(androidx.constraintlayout.constraintlayout)
testImplementation(junit.junit)
androidTestImplementation(androidx.test.ext.junit)
androidTestImplementation(androidx.test.espresso.espresso.core)
}

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,24 @@
package com.highcapable.sweetdependency.demo_library
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.highcapable.sweetdependency.demo_library.test", appContext.packageName)
}
}

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest />

View File

@@ -0,0 +1,3 @@
package com.highcapable.sweetdependency.demo_library
class DemoLibrary

View File

@@ -0,0 +1,17 @@
package com.highcapable.sweetdependency.demo_library
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@@ -0,0 +1,23 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

View File

@@ -0,0 +1,42 @@
preferences:
autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES
repositories-mode: FAIL_ON_PROJECT_REPOS
repositories:
gradle-plugin-portal:
scope: PLUGINS
google:
maven-central:
plugins:
com.android.application:
version: +
com.android.library:
version-ref: com.android.application
org.jetbrains.kotlin.android:
version: +
libraries:
com.google.android.material:
material:
version: +
androidx.constraintlayout:
constraintlayout:
version: +
junit:
junit:
version: +
androidx.appcompat:
appcompat:
version: +
androidx.core:
core:
version: +
core-ktx:
version-ref: <this>::core
androidx.test.ext:
junit:
version: +
androidx.test.espresso:
espresso-core:
version: +

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

185
examples/sample-android/gradlew vendored Normal file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
examples/sample-android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,20 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
plugins {
// Import the SweetDependency plugin here
// 在这里引入 SweetDependency 插件
id("com.highcapable.sweetdependency") version "1.0.0"
}
sweetDependency {
configFileName = "sweet-dependency-config.yaml"
isEnableDependenciesAutowireLog = true
isEnableVerboseMode = true
}
rootProject.name = "SweetDependency-Sample-Android"
include(":demo-app")
include(":demo-library")

42
examples/sample-jvm/.gitignore vendored Normal file
View File

@@ -0,0 +1,42 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@@ -0,0 +1,3 @@
plugins {
autowire(libs.plugins.org.jetbrains.kotlin.jvm) apply false
}

View File

@@ -0,0 +1 @@
kotlin.code.style=official

View File

@@ -0,0 +1,18 @@
preferences:
autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES
repositories-mode: FAIL_ON_PROJECT_REPOS
repositories:
gradle-plugin-portal:
scope: PLUGINS
google:
maven-central:
plugins:
org.jetbrains.kotlin.jvm:
version: +
libraries:
org.jetbrains.kotlin:
kotlin-test:
version: +

View File

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
examples/sample-jvm/gradlew vendored Normal file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
examples/sample-jvm/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,23 @@
plugins {
autowire(libs.plugins.org.jetbrains.kotlin.jvm)
application
}
group = "com.highcapable.sweetdependency.demo_jvm"
version = "1.0-SNAPSHOT"
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(17)
}
application {
mainClass.set("com.highcapable.sweetdependency.demo_jvm.MainKt")
}
dependencies {
testImplementation(org.jetbrains.kotlin.kotlin.test)
}

View File

@@ -0,0 +1,9 @@
package com.highcapable.sweetdependency.demo_jvm
fun main(args: Array<String>) {
println("Hello World!")
// Try adding program arguments via Run/Debug configuration.
// Learn more about running applications: https://www.jetbrains.com/help/idea/running-applications.html.
println("Program arguments: ${args.joinToString()}")
}

View File

@@ -0,0 +1,19 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
plugins {
// Import the SweetDependency plugin here
// 在这里引入 SweetDependency 插件
id("com.highcapable.sweetdependency") version "1.0.0"
}
sweetDependency {
configFileName = "sweet-dependency-config.yaml"
isEnableDependenciesAutowireLog = true
isEnableVerboseMode = true
}
rootProject.name = "SweetDependency-Sample-Jvm"
include(":sample-jvm")

19
gradle.properties Normal file
View File

@@ -0,0 +1,19 @@
# Project Configuration
project.name=SweetDependency
project.description=An easy autowire and manage dependencies Gradle plugin
project.url=https://github.com/fankes/HighCapable/SweetDependency
project.groupName=com.highcapable.sweetdependency
project.moduleName=sweet-dependency
project.version=1.0.0
project.licence.name=Apache License 2.0
project.licence.url=https://github.com/fankes/HighCapable/SweetDependency/blob/master/LICENSE
project.developer.id=0
project.developer.name=fankes
project.developer.email=qzmmcn@163.com
# Gradle Plugin Configuration
gradle.plugin.moduleName=${project.groupName}.gradle.plugin
gradle.plugin.implementationClass=${project.groupName}.plugin.SweetDependencyPlugin
# Maven Publish Configuration
maven.publish.scm.connection=scm:git:git://github.com/HighCapable/SweetDependency.git
maven.publish.scm.developerConnection=scm:git:ssh://github.com/HighCapable/SweetDependency.git
maven.publish.scm.url=https://github.com/HighCapable/SweetDependency

View File

@@ -0,0 +1,38 @@
preferences:
autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES
repositories-mode: FAIL_ON_PROJECT_REPOS
repositories:
gradle-plugin-portal:
scope: PLUGINS
google:
maven-central:
maven-local:
plugins:
org.jetbrains.kotlin.jvm:
alias: kotlin-jvm
version: 1.9.10
org.jetbrains.kotlin.plugin.serialization:
alias: kotlin-serialization
version-ref: kotlin-jvm
com.vanniktech.maven.publish:
alias: maven-publish
version: 0.25.3
libraries:
org.jetbrains.kotlin:
kotlin-gradle-plugin-api:
version: 1.9.10
org.snakeyaml:
snakeyaml-engine:
version: 2.7
com.charleskorn.kaml:
kaml:
version: 0.55.0
com.squareup.okhttp3:
okhttp:
version: 4.11.0
com.squareup:
javapoet:
version: 1.13.0

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

185
gradlew vendored Executable file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

BIN
img-src/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

30
settings.gradle.kts Normal file
View File

@@ -0,0 +1,30 @@
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
mavenLocal()
}
}
plugins {
id("com.highcapable.sweetdependency") version "1.0.0"
id("com.highcapable.sweetproperty") version "1.0.0"
}
sweetDependency {
isEnableVerboseMode = false
}
sweetProperty {
global {
sourcesCode {
className = rootProject.name
isEnableRestrictedAccess = true
}
}
rootProject { sourcesCode { isEnable = false } }
project("sweetdependency-gradle-plugin") {
buildScript { isEnableTypeAutoConversion = false }
}
}
rootProject.name = "SweetDependency"
include(":sweetdependency-gradle-plugin")

View File

@@ -0,0 +1,2 @@
.gradle
build/

View File

@@ -0,0 +1,69 @@
plugins {
`kotlin-dsl`
autowire(libs.plugins.kotlin.jvm)
autowire(libs.plugins.kotlin.serialization)
autowire(libs.plugins.maven.publish)
}
allprojects {
group = property.project.groupName
version = property.project.version
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
}
kotlin {
jvmToolchain(17)
sourceSets.all { languageSettings { languageVersion = "2.0" } }
}
dependencies {
implementation(org.jetbrains.kotlin.kotlin.gradle.plugin.api)
implementation(org.snakeyaml.snakeyaml.engine)
implementation(com.charleskorn.kaml.kaml)
implementation(com.squareup.okhttp3.okhttp)
implementation(com.squareup.javapoet)
}
gradlePlugin {
plugins {
create(property.project.moduleName) {
id = property.project.groupName
implementationClass = property.gradle.plugin.implementationClass
}
}
}
mavenPublishing {
coordinates(property.project.groupName, property.project.moduleName, property.project.version)
pom {
name = property.project.name
description = property.project.description
url = property.project.url
licenses {
license {
name = property.project.licence.name
url = property.project.licence.url
distribution = property.project.licence.url
}
}
developers {
developer {
id = property.project.developer.id
name = property.project.developer.name
email = property.project.developer.email
}
}
scm {
url = property.maven.publish.scm.url
connection = property.maven.publish.scm.connection
developerConnection = property.maven.publish.scm.developerConnection
}
}
publishToMavenCentral(com.vanniktech.maven.publish.SonatypeHost.S01)
signAllPublications()
}

View File

@@ -0,0 +1,54 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/17.
*/
package com.highcapable.sweetdependency
import com.highcapable.sweetdependency.generated.SweetDependencyProperties
/**
* [SweetDependency] 的装载调用类
*/
object SweetDependency {
/** Banner 内容 */
private const val BANNER_CONTENT = """
_____ _ _____ _
/ ____| | | | __ \ | |
| (_____ _____ ___| |_ | | | | ___ _ __ ___ _ __ __| | ___ _ __ ___ _ _
\___ \ \ /\ / / _ \/ _ \ __| | | | |/ _ \ '_ \ / _ \ '_ \ / _` |/ _ \ '_ \ / __| | | |
____) \ V V / __/ __/ |_ | |__| | __/ |_) | __/ | | | (_| | __/ | | | (__| |_| |
|_____/ \_/\_/ \___|\___|\__| |_____/ \___| .__/ \___|_| |_|\__,_|\___|_| |_|\___|\__, |
| | __/ |
|_| |___/
"""
/** Banner 内容 */
val bannerContent = BANNER_CONTENT.trimIndent()
/** 标签名称 */
const val TAG = SweetDependencyProperties.PROJECT_NAME
/** 版本 */
const val VERSION = SweetDependencyProperties.PROJECT_VERSION
/** 项目地址 */
const val PROJECT_URL = SweetDependencyProperties.PROJECT_URL
}

View File

@@ -0,0 +1,101 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/18.
*/
@file:Suppress("unused")
package com.highcapable.sweetdependency.document
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
import com.highcapable.sweetdependency.manager.content.Repositories
import com.highcapable.sweetdependency.utils.debug.SError
import com.highcapable.sweetdependency.utils.toSpaceList
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* 依赖每项文档实体
* @param alias 别名
* @param version 版本
* @param versionRef 版本引用
* @param versions 版本别名数组
* @param isAutoUpdate 是否自动更新
* @param versionFilter 版本过滤器文档实体
* @param repositories 指定使用的存储库名称
*/
@Serializable
internal data class DependencyDocument(
@SerialName("alias")
internal var alias: String = "",
@SerialName("version")
internal var version: String = "",
@SerialName("version-ref")
internal var versionRef: String = "",
@SerialName("versions")
internal var versions: MutableMap<String, String> = mutableMapOf(),
@SerialName("auto-update")
internal var isAutoUpdate: Boolean = true,
@SerialName("version-filter")
internal var versionFilter: VersionFilterDocument? = null,
@SerialName("repositories")
internal var repositories: String = ""
) : IYamlDocument {
/**
* 获取版本
* @return [DependencyVersion]
*/
internal fun version() = DependencyVersion(version)
/**
* 获取版本别名数组
* @return <[MutableMap]><[String], [DependencyVersion]>
*/
internal fun versions() = mutableMapOf<String, DependencyVersion>().also {
versions.forEach { (key, value) -> it[key] = DependencyVersion(value.replace(DependencyVersion.LATEST_VERSION_NAME, version)) }
}
/**
* 更新版本
* @param newVersion 新版本
*/
internal fun updateVersion(newVersion: DependencyVersion) {
version = newVersion.current
}
/**
* 更新版本
* @param document 当前文档实例
*/
internal fun updateVersion(document: DependencyDocument) {
version = document.version
}
/**
* 获取指定使用的存储库数组
* @return [MutableList]<[RepositoryDocument]>
*/
internal fun repositories() = mutableListOf<RepositoryDocument>().apply {
repositories.toSpaceList().forEach {
add(Repositories.all().firstOrNull { e -> e.nodeName == it } ?: SError.make("Could not found repository with name \"$it\""))
}
}.distinctBy { it.url.ifBlank { it.path } }.toMutableList()
}

View File

@@ -0,0 +1,125 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/17.
*/
package com.highcapable.sweetdependency.document
import com.highcapable.sweetdependency.document.factory.checkingName
import com.highcapable.sweetdependency.utils.camelcase
import com.highcapable.sweetdependency.utils.debug.SError
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.gradle.api.initialization.resolve.RepositoriesMode as GradleRepositoriesMode
/**
* 偏好配置项文档实体
* @param autowireOnSyncMode Gradle Sync 自动装配、更新依赖模式
* @param repositoriesMode 存储库装载模式
* @param dependenciesNamespace 依赖命名空间
* @param versionFilter 版本过滤器文档实体
*/
@Serializable
internal data class PreferencesDocument(
@SerialName("autowire-on-sync-mode")
internal var autowireOnSyncMode: AutowireOnSyncMode = AutowireOnSyncMode.UPDATE_OPTIONAL_DEPENDENCIES,
@SerialName("repositories-mode")
internal var repositoriesMode: RepositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS,
@SerialName("dependencies-namespace")
internal var dependenciesNamespace: DependenciesNamespaceDocument = DependenciesNamespaceDocument(),
@SerialName("version-filter")
internal var versionFilter: VersionFilterDocument = VersionFilterDocument()
) : IYamlDocument {
@Serializable
internal data class DependenciesNamespaceDocument(
@SerialName("plugins")
var plugins: String = "libs",
@SerialName("libraries")
var libraries: String = ""
) : IYamlDocument {
init {
if (plugins.isNotBlank() && libraries.isNotBlank() && plugins == libraries)
SError.make("Duplicated dependencies namespace \"$plugins\"")
}
/**
* 获取插件依赖命名空间
* @return [String]
*/
internal fun plugins() = plugins.apply { checkingName("plugins namespace", isCheckExtName = true) }.camelcase()
/**
* 获取库依赖命名空间
* @return [String]
*/
internal fun libraries() = libraries.apply { checkingName("libraries namespace", isCheckExtName = true) }.camelcase()
}
/**
* Gradle Sync 自动装配、更新依赖模式定义类
*/
internal enum class AutowireOnSyncMode {
/** 自动装配和更新可选依赖 (插件依赖 + 库依赖) */
UPDATE_OPTIONAL_DEPENDENCIES,
/** 自动装配和更新所有依赖 (插件依赖 + 库依赖) */
UPDATE_ALL_DEPENDENCIES,
/** 仅自动装配使用“+”填充版本的依赖 (插件依赖 + 库依赖) */
ONLY_AUTOWIRE_DEPENDENCIES,
/** 自动装配和更新可选依赖 (插件依赖) */
UPDATE_OPTIONAL_PLUGINS,
/** 自动装配和更新所有依赖 (插件依赖) */
UPDATE_ALL_PLUGINS,
/** 仅自动装配使用“+”填充版本的依赖 (插件依赖) */
ONLY_AUTOWIRE_PLUGINS,
/** 自动装配和更新可选依赖 (库依赖) */
UPDATE_OPTIONAL_LIBRARIES,
/** 自动装配和更新所有依赖 (库依赖) */
UPDATE_ALL_LIBRARIES,
/** 仅自动装配使用“+”填充版本的依赖 (库依赖) */
ONLY_AUTOWIRE_LIBRARIES,
/** 什么也不做 - 关闭所有功能 */
OFF
}
/**
* 存储库装载模式定义类 (跟随 Gradle 进行配置调整)
*/
internal enum class RepositoriesMode {
/** 参考 [GradleRepositoriesMode.PREFER_PROJECT] */
PREFER_PROJECT,
/** 参考 [GradleRepositoriesMode.PREFER_SETTINGS] */
PREFER_SETTINGS,
/** 参考 [GradleRepositoriesMode.FAIL_ON_PROJECT_REPOS] */
FAIL_ON_PROJECT_REPOS
}
}

View File

@@ -0,0 +1,273 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/17.
*/
package com.highcapable.sweetdependency.document
import com.highcapable.sweetdependency.SweetDependency
import com.highcapable.sweetdependency.manager.const.InternalRepositories
import com.highcapable.sweetdependency.manager.content.Repositories
import com.highcapable.sweetdependency.utils.debug.SError
import com.highcapable.sweetdependency.utils.parseUnixFileSeparator
import com.highcapable.sweetdependency.utils.toSpaceList
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import org.gradle.api.artifacts.repositories.PasswordCredentials
import org.gradle.api.artifacts.repositories.RepositoryContentDescriptor
/**
* 存储库配置项文档实体
* @param isEnable 是否启用
* @param scope 作用域
* @param content 内容过滤器
* @param credentials 身份验证配置项文档实体
* @param url URL 地址
* @param path 文件路径
*/
@Serializable
internal data class RepositoryDocument(
@SerialName("enable")
internal var isEnable: Boolean = true,
@SerialName("scope")
internal var scope: RepositoryScope = RepositoryScope.ALL,
@SerialName("content")
internal var content: ContentDocument = ContentDocument(),
@SerialName("credentials")
internal var credentials: CredentialsDocument = CredentialsDocument(),
@SerialName("url")
internal var url: String = "",
@SerialName("path")
internal var path: String = "",
) : IYamlDocument {
/**
* 身份验证配置项文档实体
*
* 这些内容来自 [PasswordCredentials]
* @param username 用户名
* @param password 密码
*/
@Serializable
internal data class CredentialsDocument(
@SerialName("username")
internal var username: String = "",
@SerialName("password")
internal var password: String = ""
) : IYamlDocument
/**
* 内容配置文档实体
*
* 这些内容来自 [RepositoryContentDescriptor]
* @param exclude 排除配置文档实体
* @param include 包含配置文档实体
*/
@Serializable
internal data class ContentDocument(
@SerialName("exclude")
internal var exclude: FilterDocument = FilterDocument(),
@SerialName("include")
internal var include: FilterDocument = FilterDocument()
) : IYamlDocument {
/**
* 内容过滤器配置文档实体
*
* 这些内容来自 [RepositoryContentDescriptor]
* @param group 过滤器条件内容
* @param groupAndSubgroups 过滤器条件内容
* @param groupByRegex 过滤器条件内容
* @param module 过滤器条件内容
* @param moduleByRegex 过滤器条件内容
* @param version 过滤器条件内容
* @param versionByRegex 过滤器条件内容
*/
@Serializable
internal data class FilterDocument(
@SerialName("group")
internal var group: String = "",
@SerialName("group-and-subgroups")
internal var groupAndSubgroups: String = "",
@SerialName("group-by-regex")
internal var groupByRegex: String = "",
@SerialName("module")
internal var module: String = "",
@SerialName("module-by-regex")
internal var moduleByRegex: String = "",
@SerialName("version")
internal var version: String = "",
@SerialName("version-by-regex")
internal var versionByRegex: String = ""
) : IYamlDocument {
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun group() = group.toSpaceList()
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun groupAndSubgroups() = groupAndSubgroups.toSpaceList()
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun groupByRegex() = groupByRegex.toSpaceList()
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun module() = module.toSpaceList()
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun moduleByRegex() = moduleByRegex.toSpaceList()
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun version() = version.toSpaceList()
/**
* 获取过滤器条件内容
* @return [List]<[String]>
*/
internal fun versionByRegex() = versionByRegex.toSpaceList()
/**
* 当前规则是否为空
* @return [Boolean]
*/
internal fun isEmpty() =
group.isBlank() && groupAndSubgroups.isBlank() && groupByRegex.isBlank() &&
module.isBlank() && moduleByRegex.isBlank() &&
version.isBlank() && versionByRegex.isBlank()
}
/**
* 当前规则是否为空
* @return [Boolean]
*/
internal fun isEmpty() = exclude.isEmpty() && include.isEmpty()
}
/** 节点名称 */
@Transient
internal var nodeName = ""
/** 节点类型 */
@Transient
internal var nodeType = RepositoryType.UNSPECIFIED
/**
* 存储库作用域定义类
*/
internal enum class RepositoryScope {
/** 作用于所有类型依赖 */
ALL,
/** 作用于插件依赖 */
PLUGINS,
/** 作用于库依赖 */
LIBRARIES
}
/**
* 存储库已知类型定义类
*/
internal enum class RepositoryType {
/** 未指定 */
UNSPECIFIED,
/** Google Maven */
GOOGLE,
/** 中央存储库 */
MAVEN_CENTRAL,
/** 本地存储库 */
MAVEN_LOCAL,
/** 自定义存储库 */
MAVEN,
/** Gradle Plugin 存储库 */
GRADLE_PLUGIN_PORTAL
}
/**
* 获取是否包含在作用域内
* @param isPlugins 当前类型是否为插件依赖
* @return [Boolean]
*/
internal fun isIncludeScope(isPlugins: Boolean) =
if (isPlugins) scope == RepositoryScope.ALL || scope == RepositoryScope.PLUGINS
else scope == RepositoryScope.ALL || scope == RepositoryScope.LIBRARIES
/**
* 创建当前实体
* @param name 键值名称
* @return [RepositoryDocument]
*/
internal fun build(name: String) = apply {
when (name) {
InternalRepositories.Name.GOOGLE -> {
url = url.ifBlank { InternalRepositories.GOOGLE }
nodeType = RepositoryType.GOOGLE
}
InternalRepositories.Name.MAVEN_CENTRAL -> {
url = url.ifBlank { InternalRepositories.MAVEN_CENTRAL }
nodeType = RepositoryType.MAVEN_CENTRAL
}
InternalRepositories.Name.GRADLE_PLUGIN_PORTAL -> {
url = url.ifBlank { InternalRepositories.GRADLE_PLUGIN_PORTAL }
nodeType = RepositoryType.GRADLE_PLUGIN_PORTAL
}
InternalRepositories.Name.MAVEN_LOCAL -> {
path = path.ifBlank { Repositories.defaultMavenLocalPath }
nodeType = RepositoryType.MAVEN_LOCAL
}
InternalRepositories.Name.MAVEN -> SError.make("Use \"maven\" as a repository name is an error, please choose another name")
InternalRepositories.Name.IVY -> SError.make("Ivy is not support on ${SweetDependency.TAG} ${SweetDependency.VERSION}")
else -> {
url = url.ifBlank {
Repositories.findAdditional(name).ifBlank {
SError.make("Could not found internal or additional repository URL by repository name \"$name\", you must specify a URL")
}
}; nodeType = RepositoryType.MAVEN
}
}; nodeName = name
if (url.isNotBlank() && path.isNotBlank()) SError.make("There can only be one \"url\" and \"path\" parameter of \"$name\"")
if (path.isNotBlank() && (path.startsWith("https://") || path.startsWith("http://"))) SError.make("Invalid repository path: $path")
if (url.isNotBlank() && url.startsWith("https://").not() && url.startsWith("http://").not()) SError.make("Invalid repository URL: $url")
if (path.isNotBlank()) path = path.parseUnixFileSeparator()
}
}

View File

@@ -0,0 +1,253 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/17.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
package com.highcapable.sweetdependency.document
import com.highcapable.sweetdependency.SweetDependency
import com.highcapable.sweetdependency.document.factory.DependencyMap
import com.highcapable.sweetdependency.document.factory.RepositoryList
import com.highcapable.sweetdependency.document.factory.checkingName
import com.highcapable.sweetdependency.document.factory.convertToDependencyAmbiguousName
import com.highcapable.sweetdependency.gradle.entity.DependencyName
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
import com.highcapable.sweetdependency.utils.capitalize
import com.highcapable.sweetdependency.utils.debug.SError
import com.highcapable.sweetdependency.utils.findDuplicates
import com.highcapable.sweetdependency.utils.hasDuplicate
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* 项目 (根节点) 配置文档实体
* @param preferences 偏好配置项文档实体
* @param repositories 每项存储库配置项文档实体
* @param plugins 每项插件依赖文档实体
* @param libraries 每项库依赖文档实体
* @param versions 每项版本定义数组
*/
@Serializable
internal data class RootConfigDocument(
@SerialName("preferences")
internal var preferences: PreferencesDocument? = PreferencesDocument(),
@SerialName("repositories")
internal var repositories: MutableMap<String, RepositoryDocument?>? = null,
@SerialName("plugins")
internal var plugins: MutableMap<String, DependencyDocument>? = null,
@SerialName("libraries")
internal var libraries: MutableMap<String, MutableMap<String, DependencyDocument>>? = null,
@SerialName("versions")
internal var versions: MutableMap<String, String>? = null
) : IYamlDocument {
internal companion object {
/** 默认文档内容 */
private const val DEFAULT_CONTENT = """
# SweetDependency project configuration file
# You can adjust your custom configuration to your liking here
# You can visit ${SweetDependency.PROJECT_URL} for more help
#
# SweetDependency 项目配置文件
# 你可以在这里调整你喜欢的自定义配置
# 你可以前往 ${SweetDependency.PROJECT_URL} 以获得更多帮助
# Configure preferences
# 配置偏好设置
preferences:
autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES
repositories-mode: FAIL_ON_PROJECT_REPOS
# Configure repositories used by dependencies
# 配置依赖使用的存储库
repositories:
gradle-plugin-portal:
scope: PLUGINS
google:
maven-central:
# Configure plugins that need to be used
# For example:
# plugins:
# org.jetbrains.kotlin.jvm:
# version: +
#
# 配置需要使用的插件依赖
# 例如:
# plugins:
# org.jetbrains.kotlin.jvm:
# version: +
plugins:
# Configure libraries that need to be used
# For example:
# libraries:
# com.google.code.gson:
# gson:
# version: +
#
# 配置需要使用的库依赖
# 例如:
# libraries:
# com.google.code.gson:
# gson:
# version: +
libraries:
"""
/** 默认文档内容 */
internal val defaultContent = DEFAULT_CONTENT.trimIndent()
}
/**
* 获取当前偏好配置项文档实体
* @return [PreferencesDocument]
*/
internal fun preferences() = preferences ?: PreferencesDocument()
/**
* 获取当前存储库配置项文档实体
* @return [RepositoryList]
*/
internal fun repositories() = repositories?.let {
mutableListOf<RepositoryDocument>().apply {
it.forEach { (name, repository) -> (repository ?: RepositoryDocument()).build(name).also { if (it.isEnable) add(it) } }
}
} ?: mutableListOf()
/**
* 获取当前插件依赖数组
* @param duplicate 允许重复 - 忽略处理后版本重复的异常 - 默认否
* @return [DependencyMap]
*/
internal fun plugins(duplicate: Boolean = false) = createPlugins().resolveDependencies(typeName = "plugin", duplicate)
/**
* 获取当前库依赖数组
* @param duplicate 允许重复 - 忽略处理后版本重复的异常 - 默认否
* @return [DependencyMap]
*/
internal fun libraries(duplicate: Boolean = false) = createLibraries().resolveDependencies(typeName = "library", duplicate)
/**
* 处理依赖数组
* @param typeName 依赖类型名称
* @param duplicate 允许重复 - 忽略处理后版本重复的异常 - 默认否
*/
private fun DependencyMap.resolveDependencies(typeName: String, duplicate: Boolean = false) = apply {
val firstTypeName = typeName.capitalize()
val checkDuplicateAlias = mutableMapOf<String, String>()
val refLibraries = mutableListOf<Triple<DependencyName, String, DependencyVersion>>()
val ambiguousNames = mutableListOf<String>()
eachDependencies { dependencyName, artifact ->
artifact.alias.checkingName("$typeName \"$dependencyName\" alias", isCheckMultiName = true)
artifact.versions().forEach { (name, _) -> name.checkingName("$typeName \"$dependencyName\" version alias") }
if (artifact.alias.isNotBlank())
if (checkDuplicateAlias.contains(artifact.alias).not())
checkDuplicateAlias[artifact.alias] = dependencyName.current
else SError.make(
"Duplicated alias \"${artifact.alias}\", " +
"already declared in $typeName \"${checkDuplicateAlias[artifact.alias]}\""
)
if (artifact.version().isNoSpecific && (artifact.versions().isNotEmpty() || artifact.versionRef.isNotBlank()))
SError.make(
"$firstTypeName \"$dependencyName\" has declared that it does not specify a version, " +
"so it cannot use \"versions\" or \"version-ref\""
)
if (artifact.versionRef.isNotBlank() && artifact.versionRef.startsWith("<this>::"))
artifact.versionRef = artifact.versionRef.replace("<this>:", dependencyName.groupId)
refLibraries.add(Triple(dependencyName, artifact.alias, artifact.version()))
}
eachDependencies { dependencyName, artifact ->
/** 处理版本引用 */
fun resolveVersionRef() {
refLibraries.firstOrNull { artifact.versionRef.let { e -> e == it.first.current || e == it.second } }?.also {
if (dependencyName == it.first || dependencyName.current == it.second)
SError.make("$firstTypeName \"$dependencyName\" declared \"version-ref\" from itself (recursive call found)")
when {
it.third.isNoSpecific -> SError.make(
"$firstTypeName \"${it.first}\" does not specify a version, so it can no longer be " +
"declared as \"version-ref\" by $typeName \"$dependencyName\""
)
it.third.isBlank -> SError.make(
"$firstTypeName \"${it.first}\" already has \"version-ref\" declared, so it can no longer" +
" be declared as \"version-ref\" by $typeName \"$dependencyName\" (recursive call found)"
)
}; artifact.updateVersion(it.third)
} ?: SError.make(
"Could not found any versions or dependencies associated with " +
"version-ref \"${artifact.versionRef}\" of $typeName \"$dependencyName\""
)
}
if (artifact.version().isNoSpecific) return@eachDependencies
if (artifact.version().isBlank)
if (artifact.versionRef.isNotBlank())
versions()[artifact.versionRef]?.also { artifact.version = it } ?: resolveVersionRef()
else SError.make("Missing declared version when configuring $typeName \"$dependencyName\"")
else if (artifact.version().isBlank.not() && artifact.versionRef.isNotBlank() && duplicate.not())
SError.make("$firstTypeName \"$dependencyName\" can only have one \"version\" or \"version-ref\" node, please delete one")
}
eachDependencies { dependencyName, artifact ->
ambiguousNames.add(dependencyName.ambiguousName())
if (artifact.alias.isNotBlank()) {
artifact.alias.checkingName("$typeName \"$dependencyName\" alias", isCheckMultiName = true)
ambiguousNames.add(artifact.alias.convertToDependencyAmbiguousName())
}; this[dependencyName] = artifact
}
if (ambiguousNames.hasDuplicate()) ambiguousNames.findDuplicates().forEach {
SError.make("Found ambiguous name \"$it\" in declared dependencies, please checking your $typeName aliases that your declared")
} else ambiguousNames.clear()
}
/**
* 获取当前版本定义数组
* @return [MutableMap]<[String], [String]>
*/
internal fun versions() = versions?.onEach { (name, _) -> name.checkingName("versions name") } ?: mutableMapOf()
/**
* 重新创建 [plugins]
* @return [DependencyMap]
*/
private fun createPlugins() = mutableMapOf<DependencyName, DependencyDocument>().apply {
plugins?.forEach { (notation, artifact) -> this[DependencyName.plugin(notation)] = artifact }
}
/**
* 重新创建 [libraries]
* @return [DependencyMap]
*/
private fun createLibraries() = mutableMapOf<DependencyName, DependencyDocument>().apply {
libraries?.forEach { (groupId, libraries) ->
libraries.forEach { (artifactId, artifact) -> this[DependencyName.library(groupId, artifactId)] = artifact }
}
}
/**
* 循环每项 [plugins]、[libraries]
* @param result 回调每项结果
*/
private inline fun DependencyMap.eachDependencies(result: (dependencyName: DependencyName, artifact: DependencyDocument) -> Unit) =
forEach { (dependencyName, artifact) -> result(dependencyName, artifact) }
}

View File

@@ -0,0 +1,105 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/6/9.
*/
package com.highcapable.sweetdependency.document
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
import com.highcapable.sweetdependency.manager.content.Repositories
import com.highcapable.sweetdependency.utils.filter
import com.highcapable.sweetdependency.utils.toSpaceList
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* 版本过滤器文档实体
* @param isUseInternal 使用内置过滤器
* @param exclusionList 排除列表
*/
@Serializable
internal data class VersionFilterDocument(
@SerialName("use-internal")
internal var isUseInternal: Boolean = true,
@SerialName("exclusion-list")
internal var exclusionList: String = ""
) : IYamlDocument {
/**
* 版本排除列表实体
* @param list 当前排除列表数组
*/
internal class ExclusionList internal constructor(private val list: MutableList<String>) {
/**
* 获取当前排除列表数组
* @return [MutableList]<[String]>
*/
internal fun all() = list
/**
* 当前是否存在排除列表
* @return [Boolean]
*/
internal fun isEmpty() = all().isEmpty()
/**
* 当前是否不存在排除列表
* @return [Boolean]
*/
internal fun isNotEmpty() = isEmpty().not()
/**
* 依赖于当前 [version] 提供的版本并在 [all] 中排除 (不区分大小写)
*
* 此操作会调用 [clone] 创建一个新实例并返回
* @param version 当前版本
* @return [ExclusionList]
*/
internal fun depends(version: DependencyVersion) = clone().apply {
if (version.isAutowire.not() && version.isBlank.not()) all().removeAll { version.deployed.lowercase().contains(it.lowercase()) }
}
/**
* 使用 [all] 过滤当前版本字符串 (不区分大小写)
* @param versions 当前版本字符串数组
* @return [MutableList]<[DependencyVersion]>
*/
internal fun filter(versions: MutableList<DependencyVersion>) =
if (all().isEmpty()) versions else versions.filter { version -> all().none { version.current.lowercase().contains(it.lowercase()) } }
/**
* 克隆并创建一个新实例
* @return [ExclusionList]
*/
private fun clone() = ExclusionList(mutableListOf<String>().apply { addAll(all()) })
override fun toString() = all().toString()
}
/**
* 获取排除列表
* @return [ExclusionList]
*/
internal fun exclusionList() = ExclusionList(mutableListOf<String>().apply {
if (isUseInternal) addAll(Repositories.defaultVersionFilterExclusionList)
addAll(exclusionList.toSpaceList())
})
}

View File

@@ -0,0 +1,160 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/31.
*/
package com.highcapable.sweetdependency.document.factory
import com.highcapable.sweetdependency.document.DependencyDocument
import com.highcapable.sweetdependency.document.PreferencesDocument
import com.highcapable.sweetdependency.document.RepositoryDocument
import com.highcapable.sweetdependency.gradle.entity.DependencyName
import com.highcapable.sweetdependency.gradle.entity.DependencyUpdateMode
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
import com.highcapable.sweetdependency.gradle.factory.isUnSafeExtName
import com.highcapable.sweetdependency.utils.debug.SError
import com.highcapable.sweetdependency.utils.firstNumberToLetter
/** 存储库文档实体类型定义 */
internal typealias RepositoryList = MutableList<RepositoryDocument>
/** 依赖文档实体类型定义 */
internal typealias DependencyMap = MutableMap<DependencyName, DependencyDocument>
/** 依赖文档更新实体类型定义 */
internal typealias DependencyUpdateMap = MutableMap<String, Pair<DependencyName, DependencyVersion>>
/** 依赖文档查找条件类型定义 */
internal typealias DependenciesCondition = (dependencyName: DependencyName, artifact: DependencyDocument) -> Boolean
/**
* 转换 [PreferencesDocument.AutowireOnSyncMode] 到 [DependencyUpdateMode]
*
* 如果为 [PreferencesDocument.AutowireOnSyncMode.OFF] 则会返回 null
* @return [DependencyUpdateMode] or null
*/
internal fun PreferencesDocument.AutowireOnSyncMode.toUpdateMode() = when (this) {
PreferencesDocument.AutowireOnSyncMode.UPDATE_OPTIONAL_DEPENDENCIES ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.ALL, DependencyUpdateMode.UpdateType.UPDATE_OPTIONAL)
PreferencesDocument.AutowireOnSyncMode.UPDATE_ALL_DEPENDENCIES ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.ALL, DependencyUpdateMode.UpdateType.UPDATE_ALL)
PreferencesDocument.AutowireOnSyncMode.ONLY_AUTOWIRE_DEPENDENCIES ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.ALL, DependencyUpdateMode.UpdateType.ONLY_AUTOWIRE)
PreferencesDocument.AutowireOnSyncMode.UPDATE_OPTIONAL_PLUGINS ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.PLUGINS, DependencyUpdateMode.UpdateType.UPDATE_OPTIONAL)
PreferencesDocument.AutowireOnSyncMode.UPDATE_ALL_PLUGINS ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.PLUGINS, DependencyUpdateMode.UpdateType.UPDATE_ALL)
PreferencesDocument.AutowireOnSyncMode.ONLY_AUTOWIRE_PLUGINS ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.PLUGINS, DependencyUpdateMode.UpdateType.ONLY_AUTOWIRE)
PreferencesDocument.AutowireOnSyncMode.UPDATE_OPTIONAL_LIBRARIES ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.LIBRARIES, DependencyUpdateMode.UpdateType.UPDATE_OPTIONAL)
PreferencesDocument.AutowireOnSyncMode.UPDATE_ALL_LIBRARIES ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.LIBRARIES, DependencyUpdateMode.UpdateType.UPDATE_ALL)
PreferencesDocument.AutowireOnSyncMode.ONLY_AUTOWIRE_LIBRARIES ->
DependencyUpdateMode(DependencyUpdateMode.DependencyType.LIBRARIES, DependencyUpdateMode.UpdateType.ONLY_AUTOWIRE)
PreferencesDocument.AutowireOnSyncMode.OFF -> null
}
/**
* 合并到依赖名称
* @param groupId Group ID
* @param artifactId Artifact ID
* @return [String]
*/
internal fun spliceToDependencyNotation(groupId: String, artifactId: String) = "$groupId:$artifactId"
/**
* 分离到依赖名称数组
*
* "com.mylibrary:library-core" → "com.mylibrary" | "library-core"
* @return [List]<[String]>
*/
internal fun String.splitToDependencyNames() = trim().split(":").apply { if (size != 2) SError.make("Invalid dependency name \"$this\"") }
/**
* 分离到依赖生成名称数组
*
* "com.mylibrary:library-core" → "com" | "mylibrary" | "library" | "core"
* @return [List]<[String]>
*/
internal fun String.splitToDependencyGenerateNames() =
trim().replace("_", "|").replace(".", "|").replace(":", "|").replace("-", "|").split("|").filter { it.isNotBlank() }
/**
* 转换到依赖 URL 名称
*
* "com.mylibrary:library-core" → "com/mylibrary/library-core"
* @return [String]
*/
internal fun String.convertToDependencyUrlName() = splitToDependencyNames().let { "${it[0].replace(".", "/")}/${it[1]}" }
/**
* 转换到依赖模糊分离名称 (使用 [symbol] 进行分离)
*
* "com.mylibrary:library-core" → "com[symbol]mylibrary[symbol]library[symbol]core"
* @param symbol 分隔符 - 默认 "."
* @param isReplaceFirstChar 是否使用 [firstNumberToLetter] 替换每一段第一个字符 - 默认否
* @param isLowerCase 是否全部转换为小写 - 默认是
* @return [String]
*/
internal fun String.convertToDependencyAmbiguousName(symbol: String = ".", isReplaceFirstChar: Boolean = false, isLowerCase: Boolean = true) =
mutableListOf<String>().apply {
trim().replace(".", "|").replace("_", "|").replace(":", "|").replace("-", "|").split("|").forEach {
add(if (isReplaceFirstChar) it.firstNumberToLetter() else it)
}
}.joinToString(symbol).let { if (isLowerCase) it.lowercase() else it }
/**
* 检查名称、别名是否合法
*
* - 只能包含:'0-9'、'A-Z'、'a-z'、'.'、'_'、'-' 且必须以字母开头 (长度至少为 3 位)
* - 不能是 [isUnSafeExtName]
* @param content 内容
* @param isCheckExtName 是否同时检查是否为 Gradle 使用的关键字名称 - 默认否
* @param isCheckMultiName 是否同时检查是否可被 [splitToDependencyGenerateNames] 分割为两位及以上名称 - 默认否
* @throws IllegalArgumentException 如果名称、别名不合法
*/
internal fun String.checkingName(content: String, isCheckExtName: Boolean = false, isCheckMultiName: Boolean = false) {
if (isBlank()) return
if (length < 3) SError.make("Illegal $content \"$this\", the length of $content must be >= 3")
/**
* 检查是否为 Gradle 使用的关键字名称
* @param isEnable 默认跟随 [isCheckExtName]
* @throws IllegalArgumentException 如果名称、别名不合法
*/
fun String.checkUnSafeExtName(isEnable: Boolean = isCheckExtName) {
if (isEnable && isUnSafeExtName()) SError.make("This $content \"$this\" of \"${this@checkingName}\" is a Gradle built-in extension")
}
checkUnSafeExtName()
if (isCheckMultiName) splitToDependencyGenerateNames().also { splitedNames ->
if (splitedNames.isEmpty()) SError.make("This $content \"$this\" cannot be split, please check and try again")
if (splitedNames.size < 2) SError.make("This $content \"$this\" must be able to be split into at least 2 parts")
splitedNames[0].checkUnSafeExtName(isEnable = true)
splitedNames.forEach {
if (it.first() !in 'A'..'Z' && it.first() !in 'a'..'z')
SError.make("Illegal $content \"$it\" of \"$this\", it must start with a letter")
}
}
forEachIndexed { index, char ->
if ((char !in 'A'..'Z' && char !in 'a'..'z' && index == 0) ||
(char !in 'A'..'Z' && char !in 'a'..'z' &&
char !in '0'..'9' && char != '_' && char != '-' && char != '.')
) SError.make("Illegal $content \"$this\", it only allow 26 letters (upper and lower case) and '.', '_', '-' and must start with a letter")
}
}

View File

@@ -0,0 +1,197 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/6/1.
*/
package com.highcapable.sweetdependency.document.mapping
import com.highcapable.sweetdependency.document.RootConfigDocument
import com.highcapable.sweetdependency.document.factory.DependencyUpdateMap
import com.highcapable.sweetdependency.document.factory.spliceToDependencyNotation
import com.highcapable.sweetdependency.document.mapping.entity.DependencyMapping
import com.highcapable.sweetdependency.exception.SweetDependencyUnresolvedException
import com.highcapable.sweetdependency.gradle.entity.DependencyName
import com.highcapable.sweetdependency.plugin.config.proxy.ISweetDependencyConfigs
import com.highcapable.sweetdependency.utils.debug.SError
import com.highcapable.sweetdependency.utils.debug.SLog
import com.highcapable.sweetdependency.utils.filter
import com.highcapable.sweetdependency.utils.joinToContent
import com.highcapable.sweetdependency.utils.toFile
import com.highcapable.sweetdependency.utils.yaml.Yaml
import com.highcapable.sweetdependency.utils.yaml.factory.asMap
import com.highcapable.sweetdependency.utils.yaml.factory.isKeyExist
import java.io.File
/**
* [RootConfigDocument] 的测绘实例实现类
* @param configs 当前配置
*/
internal class RootConfigDocumentMapping internal constructor(private val configs: ISweetDependencyConfigs) {
private companion object {
/** 偏好设置节点名称 */
private const val PREFERENCES_NODE_NAME = "preferences:"
/** 存储库节点名称 */
private const val REPOSITORIES_NODE_NAME = "repositories:"
/** 版本节点名称 */
private const val VERSIONS_NODE_NAME = "versions:"
/** 插件依赖节点名称 */
private const val PLUGINS_NODE_NAME = "plugins:"
/** 库依赖节点名称 */
private const val LIBRARIES_NODE_NAME = "libraries:"
/** 依赖版本起始内容 */
private const val VERSION_NODE_CONTENT = "version:"
/** 依赖版本引用节点名称 (不包括结尾的“:”) */
private const val VERSION_REF_NODE_NAME = "version-ref"
/** 4 个空格 (缩进) 内容 */
private const val SPACE_OF_4 = " "
/** 6 个空格 (缩进) 内容 */
private const val SPACE_OF_6 = " "
}
/** 当前配置文件 */
private var configFile: File? = null
/** 配置文件行内容数组 */
private val configFileContents = mutableListOf<String>()
/** 插件依赖测绘实体数组 */
private val pluginsMapping = mutableListOf<DependencyMapping>()
/** 库依赖测绘实体数组 */
private val librariesMapping = mutableListOf<DependencyMapping>()
init {
runCatching { createMapping() }.onFailure {
when (it) {
is SweetDependencyUnresolvedException -> throw it
else -> SLog.error("Failed to create config file's mapping, this will cause problem")
}
}
}
/** 创建测绘数据 */
private fun createMapping() {
configFileContents.clear()
configFileContents.addAll(configs.configFilePath.toFile().apply { configFile = this }.readText().split("\n"))
var isFoundPluginsStartLine = false
var pluginsStartLine = -1
var pluginsLine = 0
var isFoundLibrariesStartLine = false
var librariesStartLine = -1
var librariesLine = 0
val pluginsContents = mutableListOf<String>()
val librariesContents = mutableListOf<String>()
configFileContents.forEachIndexed { index, content ->
if (content.contains("\"\"")) SError.make("Character declared like -> \"\" <- are not allowed, detected at line ${index + 1}")
}
configFileContents.forEachIndexed { index, content ->
if (content.startsWith(PREFERENCES_NODE_NAME) ||
content.startsWith(REPOSITORIES_NODE_NAME) ||
content.startsWith(VERSIONS_NODE_NAME) ||
content.startsWith(LIBRARIES_NODE_NAME)
) {
isFoundPluginsStartLine = false
return@forEachIndexed
}
if (content.startsWith(PLUGINS_NODE_NAME)) {
isFoundPluginsStartLine = true
pluginsStartLine = index
}
if (isFoundPluginsStartLine) pluginsContents.add(content)
}
configFileContents.forEachIndexed { index, content ->
if (content.startsWith(PREFERENCES_NODE_NAME) ||
content.startsWith(REPOSITORIES_NODE_NAME) ||
content.startsWith(VERSIONS_NODE_NAME) ||
content.startsWith(PLUGINS_NODE_NAME)
) {
isFoundLibrariesStartLine = false
return@forEachIndexed
}
if (content.startsWith(LIBRARIES_NODE_NAME)) {
isFoundLibrariesStartLine = true
librariesStartLine = index
}
if (isFoundLibrariesStartLine) librariesContents.add(content)
}
if (pluginsContents.isNotEmpty())
Yaml.loadFromStringAsNode(pluginsContents.joinToContent()).forEach { (_, rootNode) ->
rootNode.asMap()?.forEach { (notation, artifactNode) ->
if (artifactNode.asMap()?.isKeyExist(VERSION_REF_NODE_NAME) == false)
pluginsMapping.add(DependencyMapping(notation.content))
}
}
if (librariesContents.isNotEmpty())
Yaml.loadFromStringAsNode(librariesContents.joinToContent()).forEach { (_, rootNode) ->
rootNode.asMap()?.forEach { (groupId, libraryNode) ->
libraryNode.asMap()?.forEach { (artifactId, artifactNode) ->
val notation = spliceToDependencyNotation(groupId.content, artifactId.content)
if (artifactNode.asMap()?.isKeyExist(VERSION_REF_NODE_NAME) == false)
librariesMapping.add(DependencyMapping(notation))
}
}
}
pluginsContents.onEachIndexed { index, content ->
if ((content.trim().startsWith(VERSION_NODE_CONTENT) && content.startsWith(SPACE_OF_4)).not()) return@onEachIndexed
pluginsMapping[pluginsLine].versionLine = index + pluginsStartLine
pluginsLine++
}.clear()
librariesContents.onEachIndexed { index, content ->
if ((content.trim().startsWith(VERSION_NODE_CONTENT) && content.startsWith(SPACE_OF_6)).not()) return@onEachIndexed
librariesMapping[librariesLine].versionLine = index + librariesStartLine
librariesLine++
}.clear()
}
/**
* 使用测绘数据更新依赖版本内容
* @param dependencies 需要更新的依赖名称和版本数组
*/
internal fun updateDependencies(dependencies: DependencyUpdateMap) {
/**
* 写入更新的依赖数据到文件内容
* @param dependencies 依赖数组
* @param spaceContent 空格内容
*/
fun List<DependencyMapping>.dumpToContents(dependencies: DependencyUpdateMap, spaceContent: String) =
filter { dependencies.containsKey(it.notation) }.forEach {
var codeNote = ""
val originContent = configFileContents[it.versionLine]
if (originContent.contains("#")) originContent.indexOf("#")
.also { e -> if (e > 0) codeNote = originContent.substring(e - 1..originContent.lastIndex) }
configFileContents[it.versionLine] = "$spaceContent$VERSION_NODE_CONTENT ${dependencies[it.notation]?.second?.mapped}$codeNote"
}
val plugins = dependencies.filter { it.value.first.type == DependencyName.Type.PLUGIN }
val libraries = dependencies.filter { it.value.first.type == DependencyName.Type.LIBRARY }
if (plugins.isNotEmpty()) pluginsMapping.dumpToContents(plugins, SPACE_OF_4)
if (libraries.isNotEmpty()) librariesMapping.dumpToContents(libraries, SPACE_OF_6)
if (configFileContents.isNotEmpty()) configFile?.writeText(buildString { configFileContents.forEach { append("$it\n") } }.trim())
}
}

View File

@@ -0,0 +1,29 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/6/1.
*/
package com.highcapable.sweetdependency.document.mapping.entity
/**
* 每项依赖测绘实体
* @param notation 依赖名称或 ID
* @param versionLine 版本所处行号
*/
internal data class DependencyMapping(internal var notation: String = "", internal var versionLine: Int = -1)

View File

@@ -0,0 +1,95 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/6/28.
*/
package com.highcapable.sweetdependency.environment
import com.highcapable.sweetdependency.SweetDependency
import com.highcapable.sweetdependency.generated.SweetDependencyProperties
import com.highcapable.sweetdependency.gradle.helper.GradleHelper
import com.highcapable.sweetdependency.utils.toFile
import java.io.File
/**
* [SweetDependency] 环境工具类
*/
internal object Environment {
/** [SweetDependency] 缓存存放目录 */
private const val MEMORY_DIR_PATH = ".gradle/${SweetDependencyProperties.PROJECT_MODULE_NAME}"
/** [SweetDependency] 功能存放目录 */
private const val RESOURCES_DIR_PATH = "gradle/${SweetDependencyProperties.PROJECT_MODULE_NAME}"
/**
* 获取 [SweetDependency] 缓存存放目录
* @return [File]
*/
private val memoryDir get() = "${GradleHelper.rootDir.absolutePath}/$MEMORY_DIR_PATH".toFile().also { if (it.exists().not()) it.mkdirs() }
/**
* 获取 [SweetDependency] 功能存放目录
* @return [File]
*/
private val resourcesDir get() = "${GradleHelper.rootDir.absolutePath}/$RESOURCES_DIR_PATH".toFile().also { if (it.exists().not()) it.mkdirs() }
/**
* 获取系统信息
* @return [String]
*/
internal val systemInfo get() = "${System.getProperty("os.name")} ${System.getProperty("os.version")}"
/**
* 获取字符集名称
* @return [String]
*/
internal val characterEncoding get() = System.getProperty("file.encoding")
/**
* 获取 Java 版本
* @return [String]
*/
internal val javaVersion get() = System.getProperty("java.version")
/**
* 获取 [SweetDependency] 缓存存放目录
* @param dirOrFileName 子路径目录、文件名称数组
* @return [File]
*/
internal fun memoryDir(vararg dirOrFileName: String) = memoryDir.parseDir(*dirOrFileName)
/**
* 获取 [SweetDependency] 功能存放目录
* @param dirOrFileName 子路径目录、文件名称数组
* @return [File]
*/
internal fun resourcesDir(vararg dirOrFileName: String) = resourcesDir.parseDir(*dirOrFileName)
/**
* 解析 [SweetDependency] 存放目录
* @param dirOrFileName 子路径目录、文件名称数组
* @return [File]
*/
private fun File.parseDir(vararg dirOrFileName: String): File {
var splitPath = ""
dirOrFileName.forEach { splitPath += "$it/" }
return "$absolutePath/${splitPath.ifBlank { "/" }.dropLast(1)}".toFile()
}
}

View File

@@ -0,0 +1,42 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/31.
*/
package com.highcapable.sweetdependency.exception
import com.highcapable.sweetdependency.SweetDependency
import com.highcapable.sweetdependency.utils.dumpToString
/**
* [SweetDependency] 异常定义类
* @param msg 异常内容
* @param parent 父级异常 - 默认空
*/
internal class SweetDependencyUnresolvedException internal constructor(private val msg: String, parent: Throwable? = null) : Exception(
("[${SweetDependency.TAG}] The project initialization could not be completed, please check the following for errors\n" +
"If you need help, visit ${SweetDependency.PROJECT_URL}\n" +
"* What went wrong:\n" +
"$msg\n${if (parent != null) (when (parent) {
is SweetDependencyUnresolvedException -> "* Caused by:"
else -> "* Exception is:"
} + "\n${parent.dumpToString()}") else ""}").trim()
) {
override fun toString() = "${javaClass.simpleName}: $msg"
}

View File

@@ -0,0 +1,94 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/26.
*/
package com.highcapable.sweetdependency.gradle.delegate
import com.highcapable.sweetdependency.gradle.helper.GradleHelper
import com.highcapable.sweetdependency.gradle.proxy.IGradleLifecycle
import com.highcapable.sweetdependency.utils.debug.SError
import org.gradle.api.Project
import org.gradle.api.initialization.Settings
/**
* Gradle 代理工具类
*/
internal object GradleDelegate {
/** 当前 Gradle 生命周期接口实例 */
private var lifecycle: IGradleLifecycle? = null
/**
* 创建 Gradle 生命周期 (插件) [T]
* @param settings 当前设置
*/
internal inline fun <reified T : IGradleLifecycle> create(settings: Settings) {
runCatching {
lifecycle = T::class.java.getConstructor().newInstance()
}.onFailure { SError.make("Failed to create Gradle lifecycle of \"${T::class.java}\"") }
GradleHelper.attach(settings)
callOnSettingsLoaded(settings)
settings.gradle.settingsEvaluated { callOnSettingsEvaluate(settings = this) }
settings.gradle.projectsLoaded {
callOnProjectLoaded(rootProject, isRoot = true)
rootProject.afterEvaluate { callOnProjectEvaluate(project = this, isRoot = true) }
rootProject.subprojects.forEach {
callOnProjectLoaded(it, isRoot = false)
it.afterEvaluate { callOnProjectEvaluate(project = this, isRoot = false) }
}
}
}
/**
* 调用 Gradle 开始装载事件
* @param settings 当前实例
*/
private fun callOnSettingsLoaded(settings: Settings) {
lifecycle?.onSettingsLoaded(settings)
}
/**
* 调用 Gradle 装载完成事件
* @param settings 当前实例
*/
private fun callOnSettingsEvaluate(settings: Settings) {
lifecycle?.onSettingsEvaluate(settings)
}
/**
* 调用 Gradle 开始装载项目事件
* @param project 当前项目
* @param isRoot 是否为根项目
*/
private fun callOnProjectLoaded(project: Project, isRoot: Boolean) {
if (isRoot) GradleHelper.cachingProjectList(project)
lifecycle?.onProjectLoaded(project, isRoot)
}
/**
* 调用 Gradle 项目装载完成事件
* @param project 当前项目
* @param isRoot 是否为根项目
*/
private fun callOnProjectEvaluate(project: Project, isRoot: Boolean) {
GradleHelper.cachingDependencyList(project, isRoot)
lifecycle?.onProjectEvaluate(project, isRoot)
}
}

View File

@@ -0,0 +1,63 @@
/*
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
* Copyright (C) 2019-2023 HighCapable
* https://github.com/HighCapable/SweetDependency
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is Created by fankes on 2023/5/29.
*/
package com.highcapable.sweetdependency.gradle.delegate
import org.gradle.api.Project
import kotlin.properties.Delegates
/**
* 项目事务实例实现类
*/
internal class ProjectTransaction {
internal companion object {
/** 当前项目 (当前生命周期静态) */
internal var current by Delegates.notNull<Project>()
/** 是否为根项目 (当前生命周期静态) */
internal var isRoot by Delegates.notNull<Boolean>()
}
/** 当前装载实例方法体数组 */
internal val evaluateCallbacks = mutableSetOf<((Project, Boolean) -> Unit)>()
/**
* 获取当前项目
* @return [Project]
*/
internal val current get() = Companion.current
/**
* 获取是否为根项目
* @return [Boolean]
*/
internal val isRoot get() = Companion.isRoot
/**
* 创建装载实例监听
* @param evaluate 回调装载监听 - ([Project] 当前项目,[Boolean] 师傅为根项目)
*/
internal fun evaluation(evaluate: (project: Project, isRoot: Boolean) -> Unit) {
evaluateCallbacks.add(evaluate)
}
}

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