Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.

Emit events for all known types - #127

Merged
dmdashenkov merged 46 commits into
masterfrom
emit-events-for-all-known-types
Mar 31, 2023
Merged

Emit events for all known types#127
dmdashenkov merged 46 commits into
masterfrom
emit-events-for-all-known-types

Conversation

@dmdashenkov

@dmdashenkovdmdashenkov commented Mar 17, 2023

Copy link
Copy Markdown
Contributor

In this PR we enable ProtoData plugin authors to listen to Protobuf compiler events that describe types from dependencies.

Previously, events like TypeEntered were only emitted for Proto definitions from within the module that ProtoData is processing. This is good for many cases, since this removes the need to check whether or not any code has to be generated based on a given event. However, this limited the users to only the types defined in the module. There was no way to know about a Proto message type from outside the module.

Now, we introduce a new DepdendencyDiscovered event and a ProtobufDependencyFile view. The two new types allow ProtoData plugin authors to generate code with awareness of the module's dependencies.

@dmdashenkovdmdashenkov self-assigned this Mar 17, 2023
@codecov

codecovBot commented Mar 17, 2023

Copy link
Copy Markdown

Codecov Report

Merging #127 (ff3ab1e) into master (23108f9) will increase coverage by 2.38%.
The diff coverage is 94.17%.

Additional details and impacted files
@@ Coverage Diff @@## master #127 +/- ##
============================================
+ Coverage 79.35% 81.73% +2.38% - Complexity 236 240 +4 
============================================
Files 73 79 +6 Lines 1889 1993 +104 Branches 140 146 +6 ============================================
+ Hits 1499 1629 +130 + Misses 335 313 -22 + Partials 55 51 -4 

@dmdashenkov
dmdashenkov marked this pull request as ready for review March 17, 2023 11:25
@dmdashenkov

Copy link
Copy Markdown
ContributorAuthor

@armiol, @alexander-yevsyukov, PTAL.

This is a small yet consequential change set. Let's further discuss it a video call if necessary.

@alexander-yevsyukovalexander-yevsyukov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments. In general, I think that the generation_requested flag approach should be discussed.

report_paths: '**/build/test-results/test/TEST-*.xml'
require_tests: true # will fail workflow if test reports not found

# See: https://github.com/marketplace/actions/junit-report-action

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we revert these changes please? Separation of test reports was needed some time ago when investigating build failures at CI.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmdashenkov I think this comment still stands.

@@ -68,13 +68,15 @@ internal class EnumCompilerEvents(
EnumEntered.newBuilder()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider using Kotlin DSL for Protobuf. It should be already available here. I've just tried it in another branch and it worked for me.

Comment threadapi/src/main/kotlin/io/spine/protodata/event/CompilerEvent.kt Outdated

@armiolarmiol left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmdashenkov I am now requesting changes, so that you could re-request from me, once this PR is ready. Alexander is off for a while, so it will be just me.

@dmdashenkov
dmdashenkov requested a review from armiolMarch 24, 2023 15:59
@dmdashenkov

Copy link
Copy Markdown
ContributorAuthor

@armiol, PTAL.

armiol
armiol previously requested changes Mar 24, 2023

@armiolarmiol left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmdashenkov please see my comments.

report_paths: '**/build/test-results/test/TEST-*.xml'
require_tests: true # will fail workflow if test reports not found

# See: https://github.com/marketplace/actions/junit-report-action

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmdashenkov I think this comment still stands.

RpcName rpc = 3;
}

// Emitted when a Protobuf dependency file is discovered.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this about discovering an import in our code? I am not sure what do you mean by "discovered".

// Normally, no code should be generated for dependencies. However, they can be used for additional
// info when generating code for the module's own types.
//
message DependencyDiscovered {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be more precise with this name, so that Java- and Proto-level dependencies could be distinguished.

@dmdashenkovdmdashenkovMar 27, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the doc somewhat. I'd like to avoid adding the Proto prefix because:

  • we only work with Protobuf, no Java or JS or other dependency is ever considered in ProtoData (not talking about the Gradle compiler here, only ProtoData proper);
  • this is one of a series of events such as TypeEntered, OptionDiscovered, etc., which do not specify the language either.

}

/**
* Assigns the field type and cardinality (`map`/`list`/`oneof_name`/`single`) to the receiver

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this, in fact, copying the field type and the cardinality? If so, maybe we could get rid of this "assign" term which feels a bit over-used in our domain?

* Assigns the field type and cardinality (`map`/`list`/`oneof_name`/`single`) to the receiver
* builder.
*
* @return the receiver for method chaining.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, in Kotlin we still don't put periods in @return statement descriptions.

/**
* Produces a sequence by walking through all the nested message definitions staring with `type`.
*
* @param type the message definition which may contain nested message definition to walk though

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"through"

*
* The event reflects all the definitions from the file.
*/
internal fun toDependencyEvent(fileDescriptor: Descriptors.FileDescriptor) =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about discoverDependencies(fileDescriptor: Descriptors.FileDescriptor)?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about discoverDependencies(fd: FileDescriptor)? :)

import io.spine.util.interlaced

/**
* Documentation contained in a Protobuf file.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given its description, I don't really understand why such a generic thing is now in .backend.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of the word .backend either.

This is the top-level package name for the :compiler module. :compiler serves as main implementation module for ProtoData.

Previously, Documentation, CompilerEvents, and other types where placed in the :api module in ...event package. However, it's not clear that those components belong in the :api module. Moving them to :compiler is logical since this is clearly an implementation detail (hence the internal modifier). The change of the package is a mere consequence.

I could repackage said components into ...backend.event, but I don't see much value in that right now. Would love to hear what you think.

fun fromMessage(descriptor: Descriptor): LocationPath {
val numbers = mutableListOf<Int>()
numbers.add(FileDescriptorProto.MESSAGE_TYPE_FIELD_NUMBER)
numbers.add(DescriptorProtos.FileDescriptorProto.MESSAGE_TYPE_FIELD_NUMBER)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a lot of such changes in this PR. Don't you think it's less convenient to address the types and their members by specifying a "full" (so to speak) name, rather than stripping some common parts by having them "statically" imported?

import io.spine.protodata.MessageType
import io.spine.protodata.OneofGroup
import io.spine.protodata.TypeName
import io.spine.protodata.event.FieldEntered

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the events apparently are still in io.spine.protodata.event package, I don't understand why MessageCompilerEvents isn't.

I have the same question regarding all the similar cases. Maybe, we should discuss the idea of re-packaging things into .backend as a whole. Because right now I don't understand the goal.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmdashenkov, we do need event package so that Javadocs, KDocs, and source code JARs are easier to understand. Please do have events coming under the event package.

* A type URL contains the type URL prefix and the qualified name of the type separated by
* the slash (`/`) symbol. See the docs of `google.protobuf.Any.type_url` for more info.
*/
public fun typeUrl(): String? {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the return value can really be null, please document when such a case can occur.

@alexander-yevsyukovalexander-yevsyukovMar 28, 2023

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProtoDeclarationName has a similar method that returns non-nullable String. How these two types are different in that regards?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, that was a mistake. Fixed it.

doc = documentation.forField(this@buildField)
this@field.number = this@buildField.number
this@field.declaringType = declaringType
copyTypeAndCardinality(this@buildField)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please extract this@buildField into a variable (e.g. fieldDescr, or thisField). This way you'd have fewer “dogs” around.

@alexander-yevsyukovalexander-yevsyukov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my additional comments.

declaredIn = declaringType
this@enumConstant.number = this@buildConstant.number
orderOfDeclaration = index
doc = documentation.forEnumConstant(this@buildConstant)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to the comment above, extracting this@buildConstant into a val in this block could improve the readability.

@dmdashenkov

Copy link
Copy Markdown
ContributorAuthor

@alexander-yevsyukov, @armiol, PTAL again.

@alexander-yevsyukovalexander-yevsyukov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments. Almost there.

* A type URL contains the type URL prefix and the qualified name of the type separated by
* the slash (`/`) symbol. See the docs of `google.protobuf.Any.type_url` for more info.
*/
public fun typeUrl(): String {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we have it as another property rather than a function? Just curious, how you see it.

One reason I can think of is to have shorter names in Java code. But we aim to Kotlin anyway, and we always can have @JvmName defined, should we want to.

event.option.value.unpackGuessingType() shouldBe enumValue {
name = IdempotencyLevel.NO_SIDE_EFFECTS.name
number = IdempotencyLevel.NO_SIDE_EFFECTS_VALUE
name = DescriptorProtos.MethodOptions.IdempotencyLevel.NO_SIDE_EFFECTS.name

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we import MethodOptions, please?

@dmdashenkov

Copy link
Copy Markdown
ContributorAuthor

@alexander-yevsyukov, PTAL again.

@alexander-yevsyukovalexander-yevsyukov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dmdashenkov
dmdashenkov dismissed armiol’s stale reviewMarch 31, 2023 09:10

Since we've discussed this PR in a call already.

@dmdashenkov
dmdashenkov added this pull request to the merge queue Mar 31, 2023
Merged via the queue into master with commit 621a33aMar 31, 2023
@armiol
armiol deleted the emit-events-for-all-known-types branch June 13, 2023 16:50
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@dmdashenkov@armiol@alexander-yevsyukov