mirror of
https://github.com/Instagram/LibCST.git
synced 2025-12-23 10:35:53 +00:00
address review feedback form #94
This commit is contained in:
parent
b690c591e5
commit
5f8f5c5624
3 changed files with 43 additions and 17 deletions
|
|
@ -9,15 +9,13 @@
|
|||
"==============\n",
|
||||
"Scope Analysis\n",
|
||||
"==============\n",
|
||||
"Scope analysis keeps track of assignments and accesses which could be useful for code automatic refactoring. If you're not familiar with Scope analysis, see :doc:`Metadata <metadata>` for more detail about Scope metadata. This tutorial demonstrates some use cases of Scope analysis. \n",
|
||||
"Given source codes, Scope analysis parses all variable :class:`~libcst.metadata.Assignment` (or a :class:`~libcst.metadata.BuiltinAssignment` if it's a builtin) and :class:`~libcst.metadata.Access` to store in :class:`~libcst.metadata.Scope` containers.\n",
|
||||
"\n",
|
||||
"Given the following example source code contains a couple of unused imports (``f``, ``i``, ``m`` and ``n``) and undefined variable references (``func_undefined`` and ``var_undefined``). Scope analysis helps us identifying those unused imports and undefined variables to automatically provide warnings to developers to prevent bugs while they're developing.\n",
|
||||
"With a parsed :class:`~libcst.Module`, we construct a :class:`~libcst.metadata.MetadataWrapper` object and it provides a :func:`~libcst.metadata.MetadataWrapper.resolve` function to resolve metadata given a metadata provider.\n",
|
||||
":class:`~libcst.metadata.ScopeProvider` is used here for analysing scope and there are three types of scopes (:class:`~libcst.metadata.GlobalScope`, :class:`~libcst.metadata.FunctionScope` and :class:`~libcst.metadata.ClassScope`) in this example.\n",
|
||||
"Scope analysis keeps track of assignments and accesses which could be useful for code automatic refactoring. If you're not familiar with scope analysis, see :ref:`Scope Metadata <libcst-scope-metadata>` for more detail about scope metadata. This tutorial demonstrates some use cases of scope analysis. If you're new to metadata, see :doc:`Metadata Tutorial <metadata_tutorial>` to get started.\n",
|
||||
"Given source codes, scope analysis parses all variable :class:`~libcst.metadata.Assignment` (or a :class:`~libcst.metadata.BuiltinAssignment` if it's a builtin) and :class:`~libcst.metadata.Access` to store in :class:`~libcst.metadata.Scope` containers.\n",
|
||||
"\n",
|
||||
".. note::\n",
|
||||
" The scope analysis only handles local variable name access and cannot handle simple string type annotation forward references. See :class:`~libcst.metadata.Access`\n"
|
||||
" The scope analysis only handles local variable name access and cannot handle simple string type annotation forward references. See :class:`~libcst.metadata.Access`\n",
|
||||
"\n",
|
||||
"Given the following example source code contains a couple of unused imports (``f``, ``i``, ``m`` and ``n``) and undefined variable references (``func_undefined`` and ``var_undefined``). Scope analysis helps us identifying those unused imports and undefined variables to automatically provide warnings to developers to prevent bugs while they're developing.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -38,8 +36,6 @@
|
|||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import libcst as cst\n",
|
||||
"\n",
|
||||
"source = \"\"\"\\\n",
|
||||
"import a, b, c as d, e as f # expect to keep: a, c as d\n",
|
||||
"from g import h, i, j as k, l as m # expect to keep: h, j as k\n",
|
||||
|
|
@ -56,7 +52,28 @@
|
|||
" def __new__(self) -> \"Cls\":\n",
|
||||
" var = k.method()\n",
|
||||
" func_undefined(var_undefined)\n",
|
||||
"\"\"\"\n",
|
||||
"\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "raw",
|
||||
"metadata": {
|
||||
"raw_mimetype": "text/restructuredtext"
|
||||
},
|
||||
"source": [
|
||||
"With a parsed :class:`~libcst.Module`, we construct a :class:`~libcst.metadata.MetadataWrapper` object and it provides a :func:`~libcst.metadata.MetadataWrapper.resolve` function to resolve metadata given a metadata provider.\n",
|
||||
":class:`~libcst.metadata.ScopeProvider` is used here for analysing scope and there are three types of scopes (:class:`~libcst.metadata.GlobalScope`, :class:`~libcst.metadata.FunctionScope` and :class:`~libcst.metadata.ClassScope`) in this example.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import libcst as cst\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"wrapper = cst.metadata.MetadataWrapper(cst.parse_module(source))\n",
|
||||
"scopes = set(wrapper.resolve(cst.metadata.ScopeProvider).values())\n",
|
||||
"for scope in scopes:\n",
|
||||
|
|
@ -176,7 +193,7 @@
|
|||
"raw_mimetype": "text/restructuredtext"
|
||||
},
|
||||
"source": [
|
||||
"After the transform, we use ``.code`` to generate fixed code and all unused names are fixed as expected!"
|
||||
"After the transform, we use ``.code`` to generate fixed code and all unused names are fixed as expected! The difflib is used to show only changed part and only import lines are updated as expected."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -185,8 +202,15 @@
|
|||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import difflib\n",
|
||||
"fixed_module = wrapper.module.visit(RemoveUnusedImportTransformer(unused_imports))\n",
|
||||
"print(fixed_module.code)"
|
||||
"\n",
|
||||
"# Use difflib to show the changes to verify unused imports are removed as expected.\n",
|
||||
"print(\n",
|
||||
" \"\".join(\n",
|
||||
" difflib.unified_diff(source.splitlines(1), fixed_module.code.splitlines(1))\n",
|
||||
" )\n",
|
||||
")"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue