From 72c47bb65821695d5b669dbae337520cb677a4cc Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 19:20:55 -0800 Subject: [PATCH 1/7] . --- .../reducing-conditions.mdx | 2 +- docs/tutorials/manage-feature-flags.mdx | 176 +++++++++++------- docs/tutorials/python2-to-python3.mdx | 2 + docs/tutorials/sqlalchemy-1.6-to-2.0.mdx | 4 +- docs/tutorials/training-data.mdx | 2 +- docs/tutorials/unittest-to-pytest.mdx | 4 +- 6 files changed, 118 insertions(+), 72 deletions(-) diff --git a/docs/building-with-codegen/reducing-conditions.mdx b/docs/building-with-codegen/reducing-conditions.mdx index e8ad9e739..7460308fa 100644 --- a/docs/building-with-codegen/reducing-conditions.mdx +++ b/docs/building-with-codegen/reducing-conditions.mdx @@ -1,5 +1,5 @@ --- -title: "Reducing Conditions (Advanced)" +title: "Reducing Conditions" sidebarTitle: "Reducing Conditions" icon: "code-branch" iconType: "solid" diff --git a/docs/tutorials/manage-feature-flags.mdx b/docs/tutorials/manage-feature-flags.mdx index 117b65007..24aac0924 100644 --- a/docs/tutorials/manage-feature-flags.mdx +++ b/docs/tutorials/manage-feature-flags.mdx @@ -5,73 +5,30 @@ icon: "flag" iconType: "solid" --- -Codegen SDK provides powerful APIs for managing feature flag usage in code. This guide will walk you through the basics of how to detect and clean up obsolete feature flags. +Codegen has been used in production for multi-million line codebases to automatically delete "dead" (rolled-out) feature flags. This guide will walk you through analyzing feature flag usage and safely removing rolled out flags. + + Every codebase does feature flags differently. This guide shows common techniques and syntax but likely requires adapation to codebase-specific circumstances. + -## Removing rolled out flags +## Analyzing Feature Flag Usage -Once a feature has been fully rolled out behind a flag and is stable on production, the next step is to remove old fallback code paths. +Before removing a feature flag, it's important to analyze its usage across the codebase. Codegen provides tools to help identify where and how feature flags are used. -Common syntax for feature flags include: +### For Python Codebases - - - ```python -feature_flag = codebase.get_symbol("ROLLED_OUT_FLAG_TO_DELETE") -feature_flag_name = feature_flag.name - -# Iterate over all usages of the feature flag import -for usage_symbol in feature_flag.get_all_symbol_usages(): - if isinstance(usage_symbol, Function): - # Check statements within the function - for statement in usage_symbol.code_block.get_statements(): - if isinstance(statement, IfBlockStatement) and feature_flag_name in statement.condition.source: - # Simplify the condition of the if statement - statement.reduce_condition(bool_condition=feature_flag_name == statement.condition.source) - elif isinstance(usage_symbol, Import): - # Remove the import of the feature flag - usage_symbol.remove() - ``` - - - - ```python -flag_name = "CODEMOD_RUN_SYNTAX_PREHIGHLIGHT" - -# Get the feature flag variable -feature_flag_file = codebase.get_file("codegen-backend/app/utils/posthog/feature_flags.py") -flag_class = feature_flag_file.get_class("FeatureFlag") - -# Check if the flag_var is None before proceeding -flag_var = flag_class.get_attribute(flag_name) -if not flag_var: - raise Exception(f'No such flag: {flag_name}') - -# Remove the feature flag from the class -flag_var.remove() - -# Remove all usages of the feature flag -for usage in flag_var.usages(): - # If the usage is in an if statement, remove the entire if statement - if isinstance(usage.parent, IfBlockStatement): - usage.parent.remove() - # If the usage is in a with statement, unwrap the with statement - elif isinstance(usage.parent, WithStatement): - usage.parent.code_block.unwrap() - # Otherwise, just remove the usage - else: - usage.remove() - ``` - - +For Python codebases using a `FeatureFlags` class pattern like so: +```python +class FeatureFlags: + FEATURE_1 = False + FEATURE_2 = True +``` +You can use [Class.get_attribute(...)](/api-reference/core/Class#get-attribute) and [Attribute.usages](/api-reference/core/Attribute#usages) to analyze the coverage of your flags, like so: -## Deleting unused feature flags -Detecting unused feature flag is a specific use case of [deleting dead code](/tutorials/deleting-dead-code), isolated to a specific search space. -```python Delete unused flag -print = codebase.log +```python feature_flag_usage = {} feature_flag_class = codebase.get_class('FeatureFlag') @@ -79,9 +36,9 @@ if feature_flag_class: # Initialize usage count for all attributes for attr in feature_flag_class.attributes: feature_flag_usage[attr.name] = 0 - + # Get all usages of the FeatureFlag class - for usage in feature_flag_class.usages(): + for usage in feature_flag_class.usages: usage_source = usage.usage_symbol.source if hasattr(usage, 'usage_symbol') else str(usage) for flag_name in feature_flag_usage.keys(): if f"FeatureFlag.{flag_name}" in usage_source: @@ -101,17 +58,100 @@ else: print("❗ FeatureFlag enum not found in the codebase") ``` +This will output a table showing all feature flags and their usage counts, helping identify which flags are candidates for removal. + + + Learn more about [Attributes](/building-with-codegen/class-api#class-attributes) and [tracking usages](/building-with-codegen/dependencies-and-usages) here + + + +## Removing Rolled Out Flags -#### Recommended Next Steps -Once rolled out feature flags are removed, new dead code paths may have been created. Run a delete dead code codemod to ensure complete clean-up. +Once you've identified a flag that's ready to be removed, Codegen can help safely delete it and its associated code paths. + + This primarily leverages Codegen's API for [reduction conditions](/building-with-codegen/reducing-conditions) + -## Best Practices -1. **Use Caution**: Ensure that flags have been fully rolled out before deleting. +### Python Example + +For Python codebases, here's how to remove a feature flag and its usages: + +```python +flag_name = "FEATURE_TO_REMOVE" + +# Get the feature flag variable +feature_flag_file = codebase.get_file("app/utils/feature_flags.py") +flag_class = feature_flag_file.get_class("FeatureFlag") + +# Check if the flag exists +flag_var = flag_class.get_attribute(flag_name) +if not flag_var: + print(f'No such flag: {flag_name}') + return + +# Remove all usages of the feature flag +for usage in flag_var.usages: + if isinstance(usage.parent, IfBlockStatement): + # For if statements, reduce the condition to True + usage.parent.reduce_condition(True) + elif isinstance(usage.parent, WithStatement): + # For with statements, keep the code block + usage.parent.code_block.unwrap() + else: + # For other cases, remove the usage + usage.remove() + +# Remove the flag definition +flag_var.remove() + +# Commit changes +codebase.commit() +``` + +### React/TypeScript Example + +For React applications using a hooks-based feature flag system: + +```python +feature_flag_name = "NEW_UI_ENABLED" +target_value = True # The value to reduce the flag to + +print(f'Removing feature flag: {feature_flag_name}') + +# 1. Remove from configuration +config_file = codebase.get_file("src/featureFlags/config.ts") +feature_flag_config = config_file.get_symbol("FEATURE_FLAG_CONFIG").value +if feature_flag_name in feature_flag_config.keys(): + feature_flag_config.pop(feature_flag_name) + print('✅ Removed from feature flag config') + +# 2. Find and reduce all hook usages +hook = codebase.get_function("useFeatureFlag") +for usage in hook.usages: + fcall = usage.match + if isinstance(fcall, FunctionCall): + # Check if this usage is for our target flag + first_arg = fcall.args[0].value + if isinstance(first_arg, String) and first_arg.content == feature_flag_name: + print(f'Reducing in: {fcall.parent_symbol.name}') + # This automatically handles: + # - Ternary expressions: flag ? : + # - If statements: if (flag) { ... } + # - Conditional rendering: {flag && } + fcall.reduce_condition(target_value) + +# 3. Commit changes +codebase.commit() +``` -2. **Fix Tests**: Check for additional ways feature flags are used in the codebase (e.g. string arguments in test patches). +This will: +1. Remove the feature flag from the configuration +2. Find all usages of the `useFeatureFlag` hook for this flag +3. Automatically reduce any conditional logic using the flag +4. Handle common React patterns like ternaries and conditional rendering -### Related Examples -- [reduce if statements](/building-with-codegen/reducing-conditions) -- [unwrap with statements](/building-with-codegen/statements-and-code-blocks#wrapping-and-unwrapping-statements) \ No newline at end of file +## Related Resources +- [Reducing Conditions](/building-with-codegen/reducing-conditions) - Details on condition reduction APIs +- [Dead Code Removal](/tutorials/deleting-dead-code) - Remove unused code after flag deletion \ No newline at end of file diff --git a/docs/tutorials/python2-to-python3.mdx b/docs/tutorials/python2-to-python3.mdx index 60a448768..040f38776 100644 --- a/docs/tutorials/python2-to-python3.mdx +++ b/docs/tutorials/python2-to-python3.mdx @@ -8,7 +8,9 @@ iconType: "solid" Migrating from Python 2 to Python 3 involves several syntax and API changes. This guide will walk you through using Codegen to automate this migration, handling print statements, string handling, iterators, and more. + You can find the complete example code in our [examples repository](https://github.com/codegen-sh/codegen-examples/tree/main/python2_to_python3). + ## Overview diff --git a/docs/tutorials/sqlalchemy-1.6-to-2.0.mdx b/docs/tutorials/sqlalchemy-1.6-to-2.0.mdx index d562c5544..654a5bbab 100644 --- a/docs/tutorials/sqlalchemy-1.6-to-2.0.mdx +++ b/docs/tutorials/sqlalchemy-1.6-to-2.0.mdx @@ -8,7 +8,9 @@ iconType: "solid" Migrating from [SQLAlchemy](https://www.sqlalchemy.org/) 1.6 to 2.0 involves several API changes to support the new 2.0-style query interface. This guide will walk you through using Codegen to automate this migration, handling query syntax, session usage, and ORM patterns. -You can find the complete example code in our [examples repository](https://github.com/codegen-sh/codegen-examples/tree/main/sqlalchemy_1.6_to_2.0). + +You can find the complete example code in our [examples repository](https://github.com/codegen-sh/codegen-examples/tree/main/examples/sqlalchemy_1.6_to_2.0). + ## Overview diff --git a/docs/tutorials/training-data.mdx b/docs/tutorials/training-data.mdx index 6cd9c72d1..2f8a6fba1 100644 --- a/docs/tutorials/training-data.mdx +++ b/docs/tutorials/training-data.mdx @@ -8,7 +8,7 @@ iconType: "solid" This guide demonstrates how to use Codegen to generate high-quality training data for large language models (LLMs) by extracting function implementations along with their dependencies and usages. This approach is similar to [word2vec](https://www.tensorflow.org/text/tutorials/word2vec) or [node2vec](https://snap.stanford.edu/node2vec/) - given the context of a function, learn to predict the function's implementation. -View the full code in our [examples repository](https://github.com/codegen-sh/codegen-examples/blob/main/generate_training_data/run.py) +View the full code in our [examples repository](https://github.com/codegen-sh/codegen-examples/blob/main/examples/generate_training_data/run.py) This example works with both Python and Typescript repositories without modification diff --git a/docs/tutorials/unittest-to-pytest.mdx b/docs/tutorials/unittest-to-pytest.mdx index 345c41423..5e57957ba 100644 --- a/docs/tutorials/unittest-to-pytest.mdx +++ b/docs/tutorials/unittest-to-pytest.mdx @@ -8,7 +8,9 @@ iconType: "solid" Migrating from [unittest](https://docs.python.org/3/library/unittest.html) to [pytest](https://docs.pytest.org/) involves converting test classes and assertions to pytest's more modern and concise style. This guide will walk you through using Codegen to automate this migration. -You can find the complete example code in our [examples repository](https://github.com/codegen-sh/codegen-examples/tree/main/unittest_to_pytest). + +You can find the complete example code in our [examples repository](https://github.com/codegen-sh/codegen-examples/tree/main/examples/unittest_to_pytest). + ## Overview From 4e36560e8f46ada26283a763ccfd89ace26a141c Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 19:21:22 -0800 Subject: [PATCH 2/7] . --- docs/tutorials/manage-feature-flags.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/manage-feature-flags.mdx b/docs/tutorials/manage-feature-flags.mdx index 24aac0924..41ac176a0 100644 --- a/docs/tutorials/manage-feature-flags.mdx +++ b/docs/tutorials/manage-feature-flags.mdx @@ -8,7 +8,7 @@ iconType: "solid" Codegen has been used in production for multi-million line codebases to automatically delete "dead" (rolled-out) feature flags. This guide will walk you through analyzing feature flag usage and safely removing rolled out flags. - Every codebase does feature flags differently. This guide shows common techniques and syntax but likely requires adapation to codebase-specific circumstances. + Every codebase does feature flags differently. This guide shows common techniques and syntax but likely requires adaptation to codebase-specific circumstances. ## Analyzing Feature Flag Usage From 902743b83a8d3fb6b3777207ee44a3c651ab0be7 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 20:13:10 -0800 Subject: [PATCH 3/7] . --- .../type-annotations.mdx | 209 ++++++++++++++++++ docs/introduction/faq.mdx | 3 + docs/mint.json | 1 + docs/tutorials/deleting-dead-code.mdx | 12 +- docs/tutorials/increase-type-coverage.mdx | 89 +++++--- 5 files changed, 276 insertions(+), 38 deletions(-) create mode 100644 docs/building-with-codegen/type-annotations.mdx diff --git a/docs/building-with-codegen/type-annotations.mdx b/docs/building-with-codegen/type-annotations.mdx new file mode 100644 index 000000000..7b26694df --- /dev/null +++ b/docs/building-with-codegen/type-annotations.mdx @@ -0,0 +1,209 @@ +--- +title: "Working with Type Annotations" +sidebarTitle: "Type Annotations" +icon: "code" +iconType: "solid" +--- + +This guide covers the core APIs and patterns for working with type annotations in Codegen. + +## Core Interfaces + +Type annotations in Codegen are built on two key interfaces: + +- [Typeable](/api-reference/core/Typeable) - The base interface for any node that can have a type annotation (parameters, variables, functions, etc). Provides `.type` and `.is_typed`. +- [Type](/api-reference/core/Type) - The base class for all type annotations. Provides type resolution and dependency tracking. + +Any node that inherits from `Typeable` will have a `.type` property that returns a `Type` object, which can be used to inspect and modify type annotations. + +Learn more about [inheritable behaviors](/building-with-codegen/inheritable-behaviors) like Typeable here + +## Core Type APIs + +Type annotations can be accessed and modified through several key APIs: + +### Function Types + +The main APIs for function types are [Function.return_type](/api-reference/python/PyFunction#return-type) and [Function.set_return_type](/api-reference/python/PyFunction#set-return-type): + +```python +# Get return type +return_type = function.return_type # -> TypeAnnotation +print(return_type.source) # "List[str]" +print(return_type.is_typed) # True/False + +# Set return type +function.set_return_type("List[str]") +function.set_return_type(None) # Removes type annotation +``` + +### Parameter Types + +Parameters use [Parameter.type](/api-reference/core/Parameter#type) and [Parameter.set_type_annotation](/api-reference/core/Parameter#set-type-annotation): + +```python +for param in function.parameters: + # Get parameter type + param_type = param.type # -> TypeAnnotation + print(param_type.source) # "int" + print(param_type.is_typed) # True/False + + # Set parameter type + param.set_type("int") + param.set_type(None) # Removes type annotation +``` + +### Variable Types + +Variables and attributes use [Assignment.type](/api-reference/core/Assignment#type) and [Assignment.set_type_annotation](/api-reference/core/Assignment#set-type-annotation). This applies to: +- Global variables +- Local variables +- Class attributes (via [Class.attributes](/api-reference/core/Class#attributes)) + +```python +# For global/local assignments +assignment = file.get_assignment("my_var") +var_type = assignment.type # -> TypeAnnotation +print(var_type.source) # "str" + +# Set variable type +assignment.set_type("str") +assignment.set_type(None) # Removes type annotation + +# For class attributes +class_def = file.get_class("MyClass") +for attr in class_def.attributes: + # Each attribute has an assignment property + attr_type = attr.assignment.type # -> TypeAnnotation + print(f"{attr.name}: {attr_type.source}") # e.g. "x: int" + + # Set attribute type + attr.assignment.set_type("int") + +# You can also access attributes directly by index +first_attr = class_def.attributes[0] +first_attr.assignment.set_type("str") +``` + +## Working with Complex Types + +### Union Types + +Union types ([UnionType](/api-reference/core/UnionType)) can be manipulated as collections: + +```python +# Get union type +union_type = function.return_type # -> A | B +print(union_type.symbols) # ["A", "B"] + +# Add/remove options +union_type.append("float") +union_type.remove("None") + +# Check contents +if "str" in union_type.options: + print("String is a possible type") +``` +Learn more about [working with collections here](/building-with-codegen/collections) + +### Generic Types + +Generic types ([`GenericType`](/api-reference/core/GenericType)) expose their parameters: + +```python +# Get generic type +generic_type = function.return_type # -> GenericType +print(generic_type.base) # "List" +print(generic_type.parameters) # ["str"] + +# Modify parameters +generic_type.parameters.append("int") +generic_type.parameters[0] = "float" + +# Create new generic +function.set_return_type("List[str]") +``` + +### Type Resolution + +Type resolution uses [`TypeAnnotation.resolved_types`](/api-reference/core/TypeAnnotation#resolved-types): + +```python +# Get the actual symbol for a type +type_annotation = function.return_type +resolved_symbol = type_annotation.resolved_types # -> Symbol + +# For generic types, resolve parameters +for param in type_annotation.parameters: + resolved_param = param.resolved_types +``` + +## Common Patterns + +### Checking Type Presence + +Using [`is_typed`](/api-reference/core/TypeAnnotation#is-typed) to check for type annotations: + +```python +def needs_type_annotation(function): + # Check if return type exists + if not function.return_type or not function.return_type.is_typed: + return True + + # Check if all parameters are typed + return any( + not param.type or not param.type.is_typed + for param in function.parameters + ) +``` + +### Adding Missing Types + +```python +def ensure_return_type(function, default_type="Any"): + if not function.return_type or not function.return_type.is_typed: + function.set_return_type(default_type) +``` + +### Type Inference + +Using [`ReturnStatement.value`](/api-reference/core/ReturnStatement#value) to infer types: + +```python +def infer_return_type(function): + # Look at return statements + return_types = set() + for stmt in function.return_statements: + if stmt.value and stmt.value.type: + return_types.add(stmt.value.type.source) + + # If consistent type found, use it + if len(return_types) == 1: + function.set_return_type(return_types.pop()) +``` + +### Importing Types + +Using [`File.add_symbol_import`](/api-reference/core/File#add-symbol-import) to import types: + +```python +def add_type_with_import(target_file, symbol_to_type): + # First ensure type is imported + target_file.add_symbol_import(symbol_to_type) + + # Then use in type annotation + function = target_file.get_function("my_func") + function.set_return_type(symbol_to_type.name) +``` + +## Best Practices + +1. **Check Before Setting**: Always verify if a type annotation exists and is typed before modifying +2. **Import Management**: When adding types, ensure required imports exist +3. **Type Resolution**: Use `resolved_types` when you need the actual symbol rather than just the type string +4. **Careful Modification**: When modifying generic/union types, preserve existing type parameters where appropriate + +## Related Resources +- [Increasing Type Coverage](/tutorials/increase-type-coverage) - Guide for applying these patterns +- [Dependencies and Usages](/building-with-codegen/dependencies-and-usages) - Understanding symbol relationships +- [Class API](/building-with-codegen/class-api) - Working with class attributes \ No newline at end of file diff --git a/docs/introduction/faq.mdx b/docs/introduction/faq.mdx index 7f4f9eeb6..d7f3abfba 100644 --- a/docs/introduction/faq.mdx +++ b/docs/introduction/faq.mdx @@ -20,6 +20,9 @@ iconType: "solid" Interested in adding support for your language? [Let us know](https://x.com/codegen) or [contribute](/introduction/community)! + + + Pretty much! Codegen is roughly on par with `mypy` and `tsc`. There are always edge cases in static analysis that are provably impossible to get (for example doing `eval()` on a string), but all of Codegen's APIs are intended to be exact unless otherwise specified. Please reach out if you find an edge case and we will do our best to patch it. Yes! Codegen was developed on multmillion-line Python and Typescript codebases diff --git a/docs/mint.json b/docs/mint.json index b80ab355f..a0c1e2d2f 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -111,6 +111,7 @@ "building-with-codegen/local-variables", "building-with-codegen/comments-and-docstrings", "building-with-codegen/external-modules", + "building-with-codegen/type-annotations", "building-with-codegen/moving-symbols", "building-with-codegen/collections", "building-with-codegen/traversing-the-call-graph", diff --git a/docs/tutorials/deleting-dead-code.mdx b/docs/tutorials/deleting-dead-code.mdx index 7028681c1..a750c5e85 100644 --- a/docs/tutorials/deleting-dead-code.mdx +++ b/docs/tutorials/deleting-dead-code.mdx @@ -18,7 +18,7 @@ This guide will show you how to safely identify and remove genuinely unused code ## Overview -To simply identify code without any external usages, you can check for the absence of [`Symbol.usages`](/api-reference/core/Symbol#usages). +To simply identify code without any external usages, you can check for the absence of [Symbol.usages](/api-reference/core/Symbol#usages). See [Dependencies and Usages](/building-with-codegen/dependencies-and-usages) for more information on how to use these properties. @@ -28,6 +28,9 @@ for function in codebase.functions: # Remove functions with no usages if not function.usages: function.remove() + +# Commit +codebase.commit() ``` @@ -36,7 +39,7 @@ This will remove all code that is not explicitly referenced elsewhere, including ## Filtering for Special Cases -To filter out special cases that are not explicitly referenced yet are, nonetheless, worth keeping around, you can use the following: +To filter out special cases that are not explicitly referenced yet are, nonetheless, worth keeping around, you can use the following pattern: ```python @@ -63,8 +66,10 @@ for function in codebase.functions: print(f"Removing unused function: {function.name}") # Remove the function from the file function.remove() -``` +# Commit +codebase.commit() +``` @@ -75,6 +80,7 @@ for function in codebase.functions: + diff --git a/docs/tutorials/increase-type-coverage.mdx b/docs/tutorials/increase-type-coverage.mdx index 52d833b14..95bb6970e 100644 --- a/docs/tutorials/increase-type-coverage.mdx +++ b/docs/tutorials/increase-type-coverage.mdx @@ -13,57 +13,76 @@ Common use cases include: - Checking if a generic type has a given subtype - Resolving a type annotation -## Finding the extent of your type coverage + + Adding type hints can improve developer experience and [significantly speed up](https://github.com/microsoft/Typescript/wiki/Performance#using-type-annotations) programs like the Typescript compiler and `mypy`. + -First, to get an indication of your progress on type coverage, count the number of function arguments that have type hints in your codebase: +## APIs for monitoring types - -```python python -total_parameters = 0 -typed_parameters = 0 +Codegen programs typically access type annotations through the following APIs: +- [Parameter.type](/api-reference/core/Parameter#type) +- [Function.return_type](/api-reference/python/PyFunction#return-type) +- [Assignment.type](/api-reference/core/Assignment#type) -# Iterate through all functions in the file -for function in codebase.functions: - # Count the total number of parameters - total_parameters += len(function.parameters) - # Count the number of parameters that have type hints - typed_parameters += sum(1 for param in function.parameters if param.is_typed) +Each of these has an associated setter. -# Calculate the percentage of parameters with type hints -if total_parameters > 0: - percentage_typed = (typed_parameters / total_parameters) * 100 -else: - percentage_typed = 0 -# Print the result -print(f"Percentage of function arguments with type hints: {percentage_typed:.2f}%") -``` +## Finding the extent of your type coverage -```python typescript +T to get an indication of your progress on type coverage, analyze the percentage of typed elements across your codebase + +```python +# Initialize counters for parameters total_parameters = 0 typed_parameters = 0 -# Iterate through all functions in the file +# Initialize counters for return types +total_functions = 0 +typed_returns = 0 + +# Initialize counters for class attributes +total_attributes = 0 +typed_attributes = 0 + +# Count parameter and return type coverage for function in codebase.functions: - # Count the total number of parameters + # Count parameters total_parameters += len(function.parameters) - # Count the number of parameters that have type hints typed_parameters += sum(1 for param in function.parameters if param.is_typed) -# Calculate the percentage of parameters with type hints -if total_parameters > 0: - percentage_typed = (typed_parameters / total_parameters) * 100 -else: - percentage_typed = 0 - -# Print the result -print(f"Percentage of function arguments with type hints: {percentage_typed:.2f}%") + # Count return types + total_functions += 1 + if function.return_type and function.return_type.is_typed: + typed_returns += 1 + +# Count class attribute coverage +for cls in codebase.classes: + for attr in cls.attributes: + total_attributes += 1 + if attr.is_typed: + typed_attributes += 1 + +# Calculate percentages +param_percentage = (typed_parameters / total_parameters * 100) if total_parameters > 0 else 0 +return_percentage = (typed_returns / total_functions * 100) if total_functions > 0 else 0 +attr_percentage = (typed_attributes / total_attributes * 100) if total_attributes > 0 else 0 + +# Print results +print("\nType Coverage Analysis") +print("---------------------") +print(f"Parameters: {param_percentage:.1f}% ({typed_parameters}/{total_parameters} typed)") +print(f"Return types: {return_percentage:.1f}% ({typed_returns}/{total_functions} typed)") +print(f"Class attributes: {attr_percentage:.1f}% ({typed_attributes}/{total_attributes} typed)") ``` - - +This analysis gives you a breakdown of type coverage across three key areas: +1. Function parameters - Arguments passed to functions +2. Return types - Function return type annotations +3. Class attributes - Type hints on class variables -You can perform an analogous operation for return types, method parameters, and more. Note that the code presented here only analyzes non-method functions. + + Focus first on adding types to the most frequently used functions and classes, as these will have the biggest impact on type checking and IDE support. + ## Adding simple return type annotations From 4b07ed7350121ca56147646113fb64dc97ad0d61 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 20:23:51 -0800 Subject: [PATCH 4/7] . --- docs/introduction/overview.mdx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/introduction/overview.mdx b/docs/introduction/overview.mdx index 1dab4925d..b5cfbef03 100644 --- a/docs/introduction/overview.mdx +++ b/docs/introduction/overview.mdx @@ -9,9 +9,11 @@ iconType: "solid" It provides a scriptable interface to a powerful, multi-lingual language server built on top of [Tree-sitter](https://tree-sitter.github.io/tree-sitter/). -export const metaCode = `# Codegen builds a complete graph connecting -# functions, classes, imports and their relationships -from codegen import Codebase +export const metaCode = `from codegen import Codebase + +# Codegen builds a complete graph connecting +# functions, classes, imports and their relationships +codebase = Codebase("./") # Work with code without dealing with syntax trees or parsing for function in codebase.functions: @@ -33,7 +35,7 @@ def baz():