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

split codemod into two packages. #75

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
28931c0
optionally interactive running of codemod
greenealexander Oct 20, 2023
e8b2c90
Merge pull request #1 from greenealexander/feat/non-interactive
greenealexander Oct 20, 2023
c8b4a71
forgot interactive flag
greenealexander Oct 20, 2023
8a0eeab
fix
greenealexander Oct 21, 2023
620c3a3
support destPaths
greenealexander Oct 22, 2023
03eb09f
split the project into two packages, codemon and codemon_core. The co…
bsutton Nov 16, 2023
af65cd2
modified run_interactive to use the new patch_generator
bsutton Nov 16, 2023
376d792
Moved the applyPatches and applyPatchesAndSave to the ChangeSet class.
bsutton Nov 17, 2023
677debe
Added a 'collision' list to the ChangeSet so you can get a list of ov…
bsutton Nov 17, 2023
dccb0f2
applied lint_hard and cleaned up the resulting lints.
bsutton Nov 17, 2023
aa27571
ignored ct tracker files.
bsutton Nov 17, 2023
e3f7fa5
code cleanup and improved examples and readme.
bsutton Nov 20, 2023
6b401cb
moved file_query_util into core as we needed access for examples.
bsutton Nov 20, 2023
1c122c6
updated the barrel file to reflect that file utils have been moved to…
bsutton Nov 20, 2023
9de60e9
Modified change_set so that it always creates the output file even if…
bsutton Nov 20, 2023
f6edd85
Added additional expectations for the named generated test and remove…
bsutton Nov 28, 2023
a085277
ignored .failed_tracker
bsutton Nov 28, 2023
2fbcf99
Released 1.0.1.
bsutton Nov 28, 2023
5e0a8d3
added a home page.
bsutton Nov 28, 2023
2d8e6cf
Released 1.0.1.
bsutton Nov 28, 2023
90b1082
changed patch generator to rethrow any selector exceptions as the cur…
bsutton Dec 1, 2023
6e1ec07
released 1.1.0
bsutton Jan 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
split the project into two packages, codemon and codemon_core. The co…
…demon package has exactly the same functionality as before except that the underlying ast traversal and creation of patches has been moved to codemon_core. The idea is that codemon_core can be used as an standalone API outside of the codemon CLI tooling.
  • Loading branch information
bsutton committed Nov 16, 2023
commit 03eb09f2a6b32799f24dd2e6efd1cca45e13c013
1 change: 1 addition & 0 deletions codemod/.failed_tracker
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
14 changes: 14 additions & 0 deletions codemod/example/regex_substituter_fixtures/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: regex_substituter_example
private: true
version: 0.0.0
description: regex example
publish_to: none

environment:
sdk: '>=3.0.0 <4.0.0'

dependencies:
codemod:
path: ../../
codemod_core:
path: ../../../codemod_core
File renamed without changes
8 changes: 3 additions & 5 deletions lib/codemod.dart → codemod/lib/codemod.dart
Original file line number Diff line number Diff line change
@@ -12,17 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

export 'src/aggregate.dart' show aggregate;
export 'src/ast_visiting_suggestor.dart' show AstVisitingSuggestor;
export 'src/file_context.dart' show FileContext;
export 'package:codemod_core/codemod_core.dart'
show aggregate, AstVisitingSuggestor, FileContext, Patch, Suggestor;

export 'src/file_query_util.dart'
show
filePathsFromGlob,
isHiddenFile,
isNotHiddenFile,
isDartHiddenFile,
isNotDartHiddenFile;
export 'src/patch.dart' show Patch;
export 'src/run_interactive_codemod.dart'
show runInteractiveCodemod, runInteractiveCodemodSequence;
export 'src/suggestor.dart' show Suggestor;
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -16,14 +16,12 @@ import 'dart:io';

import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:args/args.dart';
import 'package:codemod/codemod.dart';
import 'package:codemod_core/codemod_core.dart';
import 'package:io/ansi.dart';
import 'package:io/io.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;

import 'logging.dart';
import 'patch.dart';
import 'util.dart';

/// Interactively runs a "codemod" by using `stdout` to display a diff for each
69 changes: 2 additions & 67 deletions lib/src/util.dart → codemod/lib/src/util.dart
Original file line number Diff line number Diff line change
@@ -12,78 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:math' as math;
import 'dart:io';
import 'dart:math' as math;

import 'package:codemod_core/codemod_core.dart';
import 'package:io/ansi.dart';
import 'package:source_span/source_span.dart';

import 'constants.dart';
import 'patch.dart';

/// Returns the result of applying all of the [patches]
/// (insertions/deletions/replacements) to the contents of [sourceFile].
///
/// Throws an [Exception] if any two of the given [patches] overlap.
String applyPatches(SourceFile sourceFile, Iterable<Patch> patches) {
final buffer = StringBuffer();
final sortedPatches =
patches.map((p) => SourcePatch.from(p, sourceFile)).toList()..sort();

var lastEdgeOffset = 0;
late Patch prev;
for (final patch in sortedPatches) {
if (patch.startOffset < lastEdgeOffset) {
throw Exception('Codemod terminated due to overlapping patch.\n'
'Previous patch:\n'
' $prev\n'
' Updated text: ${prev.updatedText}\n'
'Overlapping patch:\n'
' $patch\n'
' Updated text: ${patch.updatedText}\n');
}

// Write unmodified text from end of last patch to beginning of this patch
buffer.write(sourceFile.getText(lastEdgeOffset, patch.startOffset));
// Write the patched text (and do nothing with the original text, which is
// effectively the same as replacing it)
buffer.write(patch.updatedText);

lastEdgeOffset = patch.endOffset;
prev = patch;
}

buffer.write(sourceFile.getText(lastEdgeOffset));
return buffer.toString();
}

/// Applies all of the [patches] (insertions/deletions/replacements) to the
/// contents of [sourceFile] and writes the result to disk.
///
/// Throws an [ArgumentError] if [sourceFile] has a null value for
/// [SourceFile.url], as it is required to open the file and write the new
/// contents.
void applyPatchesAndSave(
SourceFile sourceFile,
Iterable<Patch> patches, [
String? destPath,
]) {
if (patches.isEmpty) {
return;
}
if (sourceFile.url == null) {
throw ArgumentError('sourceFile.url cannot be null');
}
final updatedContents = applyPatches(sourceFile, patches);

if (destPath == null) {
File.fromUri(sourceFile.url!).writeAsStringSync(updatedContents);
} else {
File(destPath)
..createSync(recursive: true)
..writeAsStringSync(updatedContents);
}
}

/// Finds overlapping patches and prompts the user to decide how to handle them.
///
7 changes: 1 addition & 6 deletions lib/test.dart → codemod/lib/test.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:codemod_core/codemod_core.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

import 'src/file_context.dart';
import 'src/suggestor.dart';
import 'src/util.dart';

export 'src/util.dart' show applyPatches;

/// Creates a file with the given [name] and [sourceText] using the
/// `test_descriptor` package, sets up analysis for that file, and returns a
/// [FileContext] wrapper around it.
8 changes: 4 additions & 4 deletions pubspec.yaml → codemod/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -2,16 +2,15 @@ name: codemod
version: 1.0.11
homepage: https://github.com/Workiva/dart_codemod

description: >
Write and run automated code modifications on a codebase. Primarily geared
towards updating and refactoring Dart code, but can modify any files.
description: Write and run automated code modifications on a codebase. Primarily geared towards updating and refactoring Dart code, but can modify any files.

environment:
sdk: '>=2.12.0 <3.0.0'
sdk: '>=3.0.0 <4.0.0'

dependencies:
analyzer: ^5.0.0
args: ^2.0.0
codemod_core: ^1.0.0
glob: ^2.0.1
io: ^1.0.0
logging: ^1.0.1
@@ -29,3 +28,4 @@ dev_dependencies:
meta: ^1.6.0
mockito: ^5.3.2
pedantic: ^1.11.0
pubspec_manager: ^1.0.0-alpha.11
3 changes: 3 additions & 0 deletions codemod/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependency_overrides:
codemod_core:
path: ../codemod_core
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
// in codemod/test/aggregate_suggestor_test.dart.
// Do not manually edit this file.

import 'package:codemod/src/patch.dart' as _i2;
import 'package:codemod_core/src/patch.dart' as _i2;
import 'package:mockito/mockito.dart' as _i1;

// ignore_for_file: comment_references
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -14,10 +14,9 @@
@TestOn('vm')
import 'dart:io';

import 'package:codemod/codemod.dart';
import 'package:test/test.dart';

import 'package:codemod/src/file_query_util.dart';

void main() {
group('isHiddenFile', () {
test('returns false for non-hidden files', () {
Original file line number Diff line number Diff line change
@@ -16,13 +16,12 @@
import 'dart:convert';
import 'dart:io';

import 'package:codemod/src/run_interactive_codemod.dart' show codemodArgParser;
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

import 'package:codemod/src/run_interactive_codemod.dart' show codemodArgParser;

// Change this to `true` and all of the functional tests in this file will print
// the stdout/stderr of the codemod processes.
final _debug = false;
@@ -53,10 +52,36 @@ Future<Null> testCodemod(
// The test project has a path dependency on this codemod package, but we
// need to update it to be absolute so that it works from the temp dir.
final pubspec = File(d.path('project/pubspec.yaml'));
pubspec.writeAsStringSync(pubspec
.readAsStringSync()
.replaceAll('path: ../../../', 'path: ${p.current}'));

pubspec.writeAsStringSync(pubspec.readAsStringSync().replaceAll(
'''
codemod:
path: ../../../''',
'''
codemod:
path: ${p.current}''',
));

final pubspecOverrides = File(d.path('project/pubspec_overrides.yaml'));
pubspecOverrides
.writeAsStringSync(pubspecOverrides.readAsStringSync().replaceAll(
'''
codemod_core:
path: ../../../../codemod_core''',
'''
codemod_core:
path: ${p.current}/../codemod_core''',
));

print(pubspec.readAsStringSync());
print('pathTo ${pubspec.path}');

// final pb = PubSpec.loadFromPath(d.path('project/pubspec.yaml'));
// (pb.devDependencies['codemod'] as PathDependency).path = p.current;
// (pb.devDependencies['codemod_core'] as PathDependency).path =
// join(p.current, '..', 'codemod_core');
// pb.save();

print('running pub get in ${projectDir.io.path}');
final pubGetResult = await Process.run(
'dart',
['pub', 'get'],
3 changes: 1 addition & 2 deletions test/logging_test.dart → codemod/test/logging_test.dart
Original file line number Diff line number Diff line change
@@ -12,14 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'package:codemod_core/src/logging.dart';
@TestOn('vm')
import 'package:io/ansi.dart';
import 'package:logging/logging.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:test/test.dart';

import 'package:codemod/src/logging.dart';

import 'util.dart';

const codemodLoggerName = 'codemod';
3 changes: 1 addition & 2 deletions test/patch_test.dart → codemod/test/patch_test.dart
Original file line number Diff line number Diff line change
@@ -12,13 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'package:codemod_core/src/patch.dart';
@TestOn('vm')
import 'package:io/ansi.dart';
import 'package:source_span/source_span.dart';
import 'package:test/test.dart';

import 'package:codemod/src/patch.dart';

import 'util.dart';

final contents = '''
File renamed without changes.
50 changes: 50 additions & 0 deletions codemod/test/util_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2019 Workiva Inc.
//
// 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
//
// http://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.

@TestOn('vm')
import 'dart:io';

import 'package:codemod/src/util.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

import 'util_test.mocks.dart';

@GenerateMocks([Stdout])
void main() {
group('Utils', () {
group('calculateDiffSize()', () {
test('returns 10 if stdout does not have a terminal', () {
final mockStdout = MockStdout();
when(mockStdout.hasTerminal).thenReturn(false);
expect(calculateDiffSize(mockStdout), 10);
});

test('returns 10 if # of terminal lines is too small', () {
final mockStdout = MockStdout();
when(mockStdout.hasTerminal).thenReturn(true);
when(mockStdout.terminalLines).thenReturn(15);
expect(calculateDiffSize(mockStdout), 10);
});

test('returns 10 less than available # of terminal lines', () {
final mockStdout = MockStdout();
when(mockStdout.hasTerminal).thenReturn(true);
when(mockStdout.terminalLines).thenReturn(50);
expect(calculateDiffSize(mockStdout), 40);
});
});
});
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: codemod_test_fixture
version: 0.0.0
private: true
description: test fixture
environment:
sdk: '>=2.12.0 <3.0.0'
sdk: '>=3.0.0 <4.0.0'
dev_dependencies:
codemod:
path: ../../../
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependency_overrides:
codemod_core:
path: ../../../../codemod_core
File renamed without changes.
1 change: 1 addition & 0 deletions codemod_core/.failed_tracker
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
3 changes: 3 additions & 0 deletions codemod_core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/
3 changes: 3 additions & 0 deletions codemod_core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

- Initial version.
2 changes: 2 additions & 0 deletions codemod_core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
A sample command-line application with an entrypoint in `bin/`, library code
in `lib/`, and example unit test in `test/`.
30 changes: 30 additions & 0 deletions codemod_core/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml

# Uncomment the following section to specify additional rules.

# linter:
# rules:
# - camel_case_types

# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
Loading