Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preventing getter name conflicts in step-by-step migrations #2617

Merged
merged 6 commits into from
Sep 19, 2023

Conversation

jmatth
Copy link
Contributor

@jmatth jmatth commented Sep 18, 2023

Closes #2610.

I added a couple methods to Scope to keep track of which names have been used and allow the caller to specify how non-conflicting names should be calculated. As is this fixes the issue in my codebase with a table named entities.

In #2610 you mentioned:

This is not only a problem with table names, but also with the getter names for columns potentially colliding with columns inherited from VersionedTable (and its superclasses).

I began looking into addressing that as well but as far as I can tell any name collisions there will fail while generating Drift code for runtime. Both VersionedTable and table the table classes generated for runtime extend Table and mixin TableInfo.

Are there tests for the code generation I should be updating or adding to? I see there are tests for various parts of the drift_dev package but couldn't find any that covered SchemaVersionWriter.

Copy link
Owner

@simolus3 simolus3 left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution, this looks great!

Are there tests for the code generation I should be updating or adding to? I see there are tests for various parts of the drift_dev package but couldn't find any that covered SchemaVersionWriter.

Yeah, at the moment I'm using the generated code in examples/migrations and examples/app as an integration test for the writer, there aren't any unit tests for it. This is probably a good opportunity to get started with that, maybe something like this can serve as a starting point:

import 'package:drift/drift.dart';
import 'package:drift_dev/src/analysis/options.dart';
import 'package:drift_dev/src/analysis/results/results.dart';
import 'package:drift_dev/src/writer/import_manager.dart';
import 'package:drift_dev/src/writer/schema_version_writer.dart';
import 'package:drift_dev/src/writer/writer.dart';
import 'package:test/test.dart';

void main() {
  final fakeUri = Uri.parse('drift:hidden');

  test('avoids conflict with getters in schema class', () async {
    final imports = LibraryImportManager();
    final writer = Writer(
      const DriftOptions.defaults(),
      generationOptions: GenerationOptions(imports: imports),
    );
    imports.linkToWriter(writer);

    final table = DriftTable(
      DriftElementId(fakeUri, 'database'),
      DriftDeclaration(fakeUri, -1, ''),
      columns: [
        DriftColumn(
          sqlType: DriftSqlType.int,
          nullable: false,
          nameInSql: 'foo',
          nameInDart: 'foo',
          declaration: DriftDeclaration(fakeUri, -1, ''),
        ),
      ],
      baseDartName: 'database',
      nameOfRowClass: 'MyTableData',
    );

    SchemaVersionWriter(
      [
        SchemaVersion(
          1,
          [table],
          const {},
        ),
        SchemaVersion(
          2,
          [table],
          const {},
        ),
      ],
      writer.child(),
    ).write();

    expect(writer.writeGenerated(), contains('...'));
  });
}

@@ -298,6 +298,10 @@ class Scope extends _Node {
/// This can be used to generated methods which must have a unique name-
int counter = 0;

/// The set of names already used in this scope. Used by methos like
/// [getNonConflictingName] to prevent name collisions.
final Set<String> _usedNames = {};
Copy link
Owner

Choose a reason for hiding this comment

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

I added a couple methods to Scope to keep track of which names have been used and allow the caller to specify how non-conflicting names should be calculated

Nice idea!

drift_dev/lib/src/writer/writer.dart Outdated Show resolved Hide resolved
Copy link
Owner

@simolus3 simolus3 left a comment

Choose a reason for hiding this comment

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

The implementation looks good to me, I just have two small comments on the test.


final output = writer.writeGenerated();

print(output);
Copy link
Owner

Choose a reason for hiding this comment

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

Let's remove this debug print.

Copy link
Owner

@simolus3 simolus3 left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution!

@simolus3 simolus3 merged commit 3b81bab into simolus3:develop Sep 19, 2023
10 checks passed
@jmatth jmatth deleted the fix-migration-conflicts branch September 19, 2023 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Step-by-step migration generation fails with specific table names
2 participants