add ScopeProvider document

This commit is contained in:
Jimmy Lai 2019-09-15 22:28:21 -07:00 committed by jimmylai
parent dcf27644b5
commit 966ab81a36
4 changed files with 138 additions and 43 deletions

View file

@ -24,14 +24,14 @@
# -- Project information -----------------------------------------------------
project = 'LibCST'
copyright = '2019, Facebook'
author = 'Benjamin Woodruff, Jennifer Taylor, Carl Meyer, Jimmy Lai, Ray Zeng'
project = "LibCST"
copyright = "2019, Facebook"
author = "Benjamin Woodruff, Jennifer Taylor, Carl Meyer, Jimmy Lai, Ray Zeng"
# The short X.Y version
version = ''
version = ""
# The full version, including alpha/beta/rc tags
release = ''
release = ""
# -- General configuration ---------------------------------------------------
@ -44,25 +44,25 @@ release = ''
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'nbsphinx',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.graphviz',
'sphinx.ext.intersphinx',
'sphinx_rtd_theme',
"nbsphinx",
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.graphviz",
"sphinx.ext.intersphinx",
"sphinx_rtd_theme",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -74,7 +74,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', '**.ipynb_checkpoints']
exclude_patterns = ["_build", "**.ipynb_checkpoints"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
@ -85,7 +85,7 @@ pygments_style = None
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@ -96,7 +96,7 @@ html_theme_options = {"logo_only": True}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@ -114,7 +114,7 @@ html_favicon = "_static/logo/favicon.ico"
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'LibCSTdoc'
htmlhelp_basename = "LibCSTdoc"
# -- Options for LaTeX output ------------------------------------------------
@ -123,15 +123,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@ -141,8 +138,13 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'LibCST.tex', 'LibCST Documentation',
'Benjamin Woodruff, Jennifer Taylor', 'manual'),
(
master_doc,
"LibCST.tex",
"LibCST Documentation",
"Benjamin Woodruff, Jennifer Taylor",
"manual",
)
]
@ -150,10 +152,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'libcst', 'LibCST Documentation',
[author], 1)
]
man_pages = [(master_doc, "libcst", "LibCST Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
@ -162,9 +161,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'LibCST', 'LibCST Documentation',
author, 'LibCST', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"LibCST",
"LibCST Documentation",
author,
"LibCST",
"One line description of project.",
"Miscellaneous",
)
]
@ -183,17 +188,15 @@ epub_title = project
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
autoclass_content = "both"
autodoc_member_order = "bysource"
autodoc_default_options = {
"members": True,
"undoc-members": True,
}
autodoc_default_options = {"members": True, "undoc-members": True}
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
# -- Options for todo extension ----------------------------------------------
@ -202,19 +205,20 @@ todo_include_todos = True
# -- autodoc customization
def strip_class_signature(app, what, name, obj, options, signature, return_annotation):
if what == 'class':
if what == "class":
return (None, return_annotation)
return (signature, return_annotation)
def strip_class_signature_docstring(app, what, name, obj, options, lines):
if what == 'class':
cls_name = name.split('.')[-1]
if what == "class":
cls_name = name.split(".")[-1]
if lines and lines[0].startswith(cls_name):
while lines:
del lines[0]
def setup(app):
app.connect('autodoc-process-signature', strip_class_signature)
app.connect('autodoc-process-docstring', strip_class_signature_docstring)
app.add_css_file('custom.css')
app.connect("autodoc-process-signature", strip_class_signature)
app.connect("autodoc-process-docstring", strip_class_signature_docstring)
app.add_css_file("custom.css")

View file

@ -89,4 +89,25 @@ Expression Context Metadata
.. autoclass:: libcst.ExpressionContextProvider
:no-undoc-members:
.. autoclass:: libcst.ExpressionContext
.. autoclass:: libcst.ExpressionContext
Scope Metadata
--------------
.. autoclass:: libcst.ScopeProvider
.. autoclass:: libcst.BaseAssignment
:no-undoc-members:
.. autoclass:: libcst.Assignment
.. autoclass:: libcst.BuiltinAssignmemt
.. autoclass:: libcst.Access
.. autoclass:: libcst.Scope
:no-undoc-members:
.. autoclass:: libcst.GlobalScope
:no-undoc-members:
.. autoclass:: libcst.FunctionScope
.. autoclass:: libcst.ClassScope
.. autoclass:: libcst.ComprehensionScope

View file

@ -200,6 +200,18 @@ from libcst.metadata.position_provider import (
BasicPositionProvider,
SyntacticPositionProvider,
)
from libcst.metadata.scope_provider import (
Access,
Assignment,
BaseAssignment,
BuiltinAssignmemt,
ClassScope,
ComprehensionScope,
FunctionScope,
GlobalScope,
Scope,
ScopeProvider,
)
from libcst.metadata.wrapper import MetadataWrapper
@ -396,4 +408,14 @@ __all__ = [
"MetadataWrapper",
"ExpressionContext",
"ExpressionContextProvider",
"BaseAssignment",
"Assignment",
"BuiltinAssignmemt",
"Access",
"Scope",
"GlobalScope",
"FunctionScope",
"ClassScope",
"ComprehensionScope",
"ScopeProvider",
]

View file

@ -13,6 +13,7 @@ from dataclasses import dataclass
from typing import Dict, Iterator, List, MutableMapping, Optional, Tuple, Type, Union
import libcst as cst
from libcst._add_slots import add_slots
from libcst.metadata.base_provider import BatchableMetadataProvider
from libcst.metadata.expression_context_provider import (
ExpressionContext,
@ -20,14 +21,28 @@ from libcst.metadata.expression_context_provider import (
)
@add_slots
@dataclass(frozen=True)
class Access:
"""
Access records an access of an assignment.
"""
#: The name node of the access. A name is an access when the expression context is
#: :attr:`ExpressionContext.LOAD`.
node: cst.Name
#: The scope of the access. Note that a access could be in a child scope of its assignment.
scope: "Scope"
class BaseAssignment(abc.ABC):
"""Abstract base class of :class:`Assignment` and :class:`BuitinAssignment`."""
#: The name of assignment.
name: str
#: The scope associates to assignment.
scope: "Scope"
__accesses: List[Access]
@ -41,11 +56,16 @@ class BaseAssignment(abc.ABC):
@property
def accesses(self) -> Tuple[Access, ...]:
"""Return all accesses of the assignment."""
# we don't want to publicly expose the mutable version of this
return tuple(self.__accesses)
class Assignment(BaseAssignment):
"""An assignment records the name, CSTNode and its accesses."""
#: The node of assignment, it could be a :class:`~libcst.Import`, :class:`ImportFrom`,
#: :class:`~libcst.Name`, :class:`~libcst.FunctionDef`, or :class:`~libcst.ClassDef`.
node: cst.CSTNode
def __init__(self, name: str, scope: "Scope", node: cst.CSTNode) -> None:
@ -54,11 +74,31 @@ class Assignment(BaseAssignment):
class BuiltinAssignmemt(BaseAssignment):
"""
A BuiltinAssignment represents an value provide by Python as a builtin, including
`functions <https://docs.python.org/3/library/functions.html>`_,
`constants <https://docs.python.org/3/library/constants.html>`_, and
`types <https://docs.python.org/3/library/stdtypes.html>`_.
"""
pass
class Scope(abc.ABC):
"""
Base class of all scope classes. Scope object stores assignments from imports,
variable assignments, function definition or class definition.
A scope has a parent scope which represents the inheritance relationship. That means
an assignment in parent scope is viewable to the child scope and the child scope may
overwrites the assignment by using the same name.
Use ``name in scope`` to check whether a name is viewable in the scope.
Use ``scope[name]`` to retrieve all viewable assignments in the scope.
"""
#: Parent scope. Note the parent scope of a GlobalScope is itself.
parent: "Scope"
#: Refers to the GlobalScope.
globals: "GlobalScope"
_assignments: MutableMapping[str, List[BaseAssignment]]
@ -96,6 +136,10 @@ class Scope(abc.ABC):
class GlobalScope(Scope):
"""
GlobalScope is the scope of module. All module level assignments are recorded in GlobalScope.
"""
def __init__(self) -> None:
self.globals: Scope = self # must be defined before Scope.__init__ is called
super().__init__(parent=self)
@ -144,6 +188,10 @@ class LocalScope(Scope, abc.ABC):
class FunctionScope(LocalScope):
"""
When a function is defined, it creates a FunctionScope.
"""
pass