Skip to content

Commit

Permalink
Merge branch 'develop' into feature/docs
Browse files Browse the repository at this point in the history
  • Loading branch information
theEvilReaper committed Mar 10, 2024
2 parents 22bb33f + f5e3da5 commit fd73dbb
Show file tree
Hide file tree
Showing 87 changed files with 2,822 additions and 662 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/maven-central.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ on:
branches:
- main
- develop
workflow_run:
workflows:
- "Test PR"
types:
- completed
release:
types: [created]
jobs:
Expand All @@ -28,9 +33,9 @@ jobs:
distribution: 'adopt'

- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
uses: gradle/wrapper-validation-action@v2
- name: Publish package
uses: gradle/gradle-build-action@v2
uses: gradle/actions/setup-gradle@v3
with:
arguments: publishMavenJavaPublicationToMavenRepository
env:
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/test-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test PR
on: [pull_request]
jobs:
build_pr:
if: github.repository_owner == 'theEvilReaper'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: Build with ${{ matrix.os }}
run: |
git config --global user.email "no-reply@github.com"
git config --global user.name "Github Actions"
./gradlew test
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ repositories {
}

dependencies {
compileOnly(libs.jetbrains.annotations)
testImplementation(kotlin("test"))
testImplementation(libs.google.truth)
testImplementation(libs.junit.api)
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
10 changes: 5 additions & 5 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ rootProject.name = "DartPoet"
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
version("junit", "5.10.1")
library("google.truth", "com.google.truth", "truth").version("1.2.0")
version("junit", "5.10.2")
library("google.truth", "com.google.truth", "truth").version("1.4.2")
library("junit.api", "org.junit.jupiter", "junit-jupiter-api").versionRef("junit")
library("junit.engine", "org.junit.jupiter", "junit-jupiter-engine").versionRef("junit")
library("junit.params", "org.junit.jupiter", "junit-jupiter-params").versionRef("junit")

library("jetbrains.annotations", "org.jetbrains", "annotations").version("24.1.0")
plugin("changelog", "org.jetbrains.changelog").version("2.2.0")
plugin("dokka", "org.jetbrains.dokka").version("1.9.10")
plugin("kotlin.jvm", "org.jetbrains.kotlin.jvm").version("1.9.22")
plugin("dokka", "org.jetbrains.dokka").version("1.9.20")
plugin("kotlin.jvm", "org.jetbrains.kotlin.jvm").version("1.9.23")
}
}
}
61 changes: 34 additions & 27 deletions src/main/kotlin/net/theevilreaper/dartpoet/DartFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import net.theevilreaper.dartpoet.clazz.ClassSpec
import net.theevilreaper.dartpoet.code.CodeWriter
import net.theevilreaper.dartpoet.code.buildCodeString
import net.theevilreaper.dartpoet.code.writer.DartFileWriter
import net.theevilreaper.dartpoet.extension.ExtensionSpec
import net.theevilreaper.dartpoet.function.FunctionSpec
import net.theevilreaper.dartpoet.util.*
import net.theevilreaper.dartpoet.directive.DartDirective
import net.theevilreaper.dartpoet.directive.ExportDirective
import net.theevilreaper.dartpoet.directive.LibraryDirective
import net.theevilreaper.dartpoet.directive.PartDirective
import net.theevilreaper.dartpoet.directive.RelativeDirective
import net.theevilreaper.dartpoet.extension.ExtensionSpec
import net.theevilreaper.dartpoet.function.FunctionSpec
import net.theevilreaper.dartpoet.util.*
import net.theevilreaper.dartpoet.property.consts.ConstantPropertySpec
import net.theevilreaper.dartpoet.util.DART_FILE_ENDING
import net.theevilreaper.dartpoet.util.isDartConventionFileName
Expand All @@ -30,36 +32,29 @@ class DartFile internal constructor(
internal val types: List<ClassSpec> = builder.specTypes.toImmutableList()
internal val extensions: List<ExtensionSpec> = builder.extensionStack
internal val docs = builder.docs
private val directives = builder.directives.toImmutableList()
internal val constants: Set<ConstantPropertySpec> = builder.constants.toImmutableSet()

internal val imports: List<DartDirective> = if (directives.isEmpty()) {
emptyList()
} else {
builder.directives.filterIsInstance<DartDirective>().toList()
}
private val directives = builder.directives.toImmutableList()

internal val partImports: List<PartDirective> = if (directives.isEmpty()) {
emptyList()
} else {
builder.directives.filterIsInstance<PartDirective>().toList()
}
internal val dartImports =
DirectiveOrdering.sortDirectives<DartDirective>(DartDirective::class, directives) { it.contains("dart:") }
internal val packageImports =
DirectiveOrdering.sortDirectives<DartDirective>(DartDirective::class, directives) { it.contains("package:") }
internal val partImports = DirectiveOrdering.sortDirectives<PartDirective>(PartDirective::class, directives)
internal val libImport = DirectiveOrdering.sortDirectives<LibraryDirective>(LibraryDirective::class, directives)
internal val exportDirectives =
DirectiveOrdering.sortDirectives<ExportDirective>(ExportDirective::class, directives)
internal val relativeImports =
DirectiveOrdering.sortDirectives<RelativeDirective>(RelativeDirective::class, directives)

internal val libImport: LibraryDirective? = if (directives.isEmpty()) {
null
} else {
val possibleListImports = directives.filterIsInstance<LibraryDirective>()
if (possibleListImports.isEmpty()) {
null
} else if (possibleListImports.size == 1) {
possibleListImports.first()
} else {
throw Exception("Only one library import is allowed")
}
}
internal val typeDefs = builder.typeDefs.toImmutableList()
internal val hasTypeDefs = typeDefs.isNotEmpty()

init {
check(name.trim().isNotEmpty()) { "The name of a class can't be empty (ONLY SPACES ARE NOT ALLOWED" }
if (libImport.isNotEmpty()) {
check(libImport.size == 1) { "Only one library directive is allowed" }
}
}

internal fun write(codeWriter: CodeWriter) {
Expand All @@ -80,7 +75,11 @@ class DartFile internal constructor(
}
}


/**
* Writes the content from a [DartFile] to the given [Appendable].
* @param out the [Appendable] where the content should be written
* @throws IOException if the content can't be written
*/
@Throws(IOException::class)
fun write(out: Appendable) {
val codeWriter = CodeWriter(
Expand All @@ -91,6 +90,11 @@ class DartFile internal constructor(
codeWriter.close()
}

/**
* Writes the content from a [DartFile] to the given [Path].
* @param path the path where the file should be written
* @throws IOException if the file can't be written
*/
@Throws(IOException::class)
fun write(path: Path) {
require(Files.notExists(path) || Files.isDirectory(path)) {
Expand Down Expand Up @@ -131,6 +135,9 @@ class DartFile internal constructor(
return builder
}

/**
* Creates a new instance of [DartFileBuilder] with the specified name.
*/
companion object {

/**
Expand Down
20 changes: 20 additions & 0 deletions src/main/kotlin/net/theevilreaper/dartpoet/DartFileBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import net.theevilreaper.dartpoet.clazz.ClassSpec
import net.theevilreaper.dartpoet.code.CodeBlock
import net.theevilreaper.dartpoet.extension.ExtensionSpec
import net.theevilreaper.dartpoet.directive.Directive
import net.theevilreaper.dartpoet.function.typedef.TypeDefSpec
import net.theevilreaper.dartpoet.property.consts.ConstantPropertySpec
import net.theevilreaper.dartpoet.property.PropertySpec
import net.theevilreaper.dartpoet.util.DEFAULT_INDENT
Expand All @@ -20,6 +21,7 @@ class DartFileBuilder(
internal val annotations: MutableList<AnnotationSpec> = mutableListOf()
internal val extensionStack: MutableList<ExtensionSpec> = mutableListOf()
internal val constants: MutableSet<ConstantPropertySpec> = mutableSetOf()
internal val typeDefs: MutableList<TypeDefSpec> = mutableListOf()
internal var indent = DEFAULT_INDENT

/**
Expand Down Expand Up @@ -71,6 +73,24 @@ class DartFileBuilder(
this.extensionStack += extensions
}

/**
* Add a type definition to the file builder.
* @param typeDef the type definition to add
* @return the current instance of [DartFileBuilder]
*/
fun typeDef(typeDef: TypeDefSpec) = apply {
this.typeDefs += typeDef
}

/**
* Add an array of type definitions to the file builder.
* @param typeDef the type definitions to add
* @return the current instance of [DartFileBuilder]
*/
fun typeDef(vararg typeDef: TypeDefSpec) = apply {
this.typeDefs += typeDef
}

fun type(dartFileSpec: ClassSpec) = apply {
this.specTypes += dartFileSpec
}
Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/net/theevilreaper/dartpoet/DartModifier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ enum class DartModifier(
internal val identifier: String,
private vararg val modifiers: ModifierTarget
) {

PUBLIC("", ModifierTarget.CLASS, ModifierTarget.PROPERTY, ModifierTarget.FUNCTION),
PRIVATE("_", ModifierTarget.FUNCTION, ModifierTarget.PROPERTY),
STATIC("static", ModifierTarget.FUNCTION, ModifierTarget.PROPERTY),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.theevilreaper.dartpoet.annotation

import net.theevilreaper.dartpoet.code.*
import net.theevilreaper.dartpoet.code.buildCodeString
import net.theevilreaper.dartpoet.code.writer.AnnotationWriter
import net.theevilreaper.dartpoet.type.ClassName
import net.theevilreaper.dartpoet.type.TypeName
Expand All @@ -10,26 +9,37 @@ import net.theevilreaper.dartpoet.util.toImmutableSet
import kotlin.reflect.KClass

/**
* The [AnnotationSpec] contain all relevant data about a annotation.
* The [AnnotationSpec] class encapsulates essential data that defines a metadata / annotation structure.
* Annotations can be used in Dart to add additional information to the code base.
* Typically, an annotation starts with the character @, followed by an identifier,
* and optionally with meta information which are encapsulated in round brackets.
* It's important to note that you can't really use the predefined annotations from the JDK or Kotlin because the languages are not interoperable to Dart,
*
* Common annotations from Dart:
* - @deprecated,
* - @override
* - @pragma
* @param builder the builder instance to retrieve the data from
* @author theEvilReaper
* @version 1.0.0
* @since
**/
* @since 1.0.0
*/
class AnnotationSpec(
builder: AnnotationSpecBuilder
builder: AnnotationSpecBuilder,
) {

internal val typeName: TypeName = builder.typeName
internal val content: Set<CodeBlock> = builder.content.toImmutableSet()
internal val hasMultipleContentParts = content.size > 1
internal val hasContent: Boolean = content.isNotEmpty()
internal val hasMultipleContentParts: Boolean = content.size > 1

/**
* Triggers an [AnnotationWriter] to write the spec object into code.
* Triggers the write process for an [AnnotationSpec] object.
* @param codeWriter the [CodeWriter] instance to write the spec to
* @param inline if the spec should be written inline
*/
internal fun write(
codeWriter: CodeWriter,
inline: Boolean = true
inline: Boolean = true,
) {
AnnotationWriter().emit(this, codeWriter, inline = inline)
}
Expand All @@ -51,18 +61,48 @@ class AnnotationSpec(
return builder
}

/**
* The companion object contains some helper methods to create a new instance from the [AnnotationSpecBuilder].
*/
companion object {

/**
* Creates a new instance from the [AnnotationSpecBuilder].
* @return the created instance
* @param name the name for the annotation provided as [String]
* @return the created instance from the [AnnotationSpecBuilder]
*/
@JvmStatic
fun builder(name: String) = AnnotationSpecBuilder(ClassName(name))

/**
* Creates a new instance from the [AnnotationSpecBuilder].
* @param type the type for the annotation provided as [ClassName]
* @return the created instance from the [AnnotationSpecBuilder]
*/
@JvmStatic
fun builder(type: ClassName) = AnnotationSpecBuilder(type)

/**
* Creates a new instance from the [AnnotationSpecBuilder].
* @param type the type for the annotation provided as [TypeName]
* @return the created instance from the [AnnotationSpecBuilder]
*/
@JvmStatic
fun builder(type: TypeName) = AnnotationSpecBuilder(type)

/**
* Creates a new instance from the [AnnotationSpecBuilder].
* @param type the type for the annotation provided as [Class]
* @return the created instance from the [AnnotationSpecBuilder]
*/
@JvmStatic
fun builder(type: Class<*>) = AnnotationSpecBuilder(type.asClassName())

/**
* Creates a new instance from the [AnnotationSpecBuilder].
* @param type the type for the annotation provided as [KClass]
* @return the created instance from the [AnnotationSpecBuilder]
*/
@JvmStatic
fun builder(type: KClass<out Annotation>) = AnnotationSpecBuilder(type.asClassName())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,42 @@ import net.theevilreaper.dartpoet.type.TypeName
* With the AnnotationBuilder data can be set to an annotation.
* These are later read out during generation and converted into code accordingly.
* @author theEvilReaper
* @param typeName the name of the annotation
* @version 1.0.0
* @since
**/
class AnnotationSpecBuilder(
internal val typeName: TypeName
) {

/**
* Stores the content parts from the annotation.
*/
internal val content: MutableList<CodeBlock> = mutableListOf()

/**
* Add a content part to the annotation.
* @param format the format string
* @param args the arguments for the format string
* @return the given instance of an [AnnotationSpecBuilder]
*/
fun content(format: String, vararg args: Any) = apply {
content(CodeBlock.of(format, *args))
}

/**
* Add a content part to the annotation.
* @param codeFragment the code fragment to add provided as [CodeBlock]
* @return the given instance of an [AnnotationSpecBuilder]
*/
fun content(codeFragment: CodeBlock) = apply {
this.content += codeFragment
}

/**
* Add a content part to the annotation.
* @param codeFragment the code fragment to add provided as lambda block
* @return the given instance of an [AnnotationSpecBuilder]
*/
fun content(codeFragment: () -> CodeBlock) = apply {
this.content += codeFragment()
}
Expand Down
Loading

0 comments on commit fd73dbb

Please sign in to comment.