def _build_way_geometry(
    way_id: int,
    way_nodes: list[int],
    way_tags: dict[str, Any],
    node_coords: dict[int, tuple[float, float]],
) -> LineString | Polygon:
    """
    Build a way's geometry from its constituent nodes' coordinates.

    A way can be a LineString (open or closed way) or a Polygon (closed way)
    but multi-geometries and polygons with holes are represented as relations.
    See documentation: https://wiki.openstreetmap.org/wiki/Way#Types_of_ways

    Parameters
    ----------
    way_id
        The way's OSM ID.
    way_nodes
        The way's constituent nodes.
    way_tags
        The way's tags.
    node_coords
        Keyed by OSM node ID with values of `(lat, lon)` coordinate tuples.

    Returns
    -------
    geometry
        The way's geometry.
    """
    # a way is a LineString by default, but if it's a closed way and it's not
    # tagged area=no, check if any of its tags denote it as a polygon instead
    geom_type = LineString
    if way_nodes[0] == way_nodes[-1] and way_tags.get("area") != "no":
        for tag in way_tags.keys() & _POLYGON_FEATURES.keys():
            rule = _POLYGON_FEATURES[tag]["polygon"]
            values = _POLYGON_FEATURES[tag].get("values", set())
            if (
                rule == "all"
                or (rule == "passlist" and way_tags[tag] in values)
                or (rule == "blocklist" and way_tags[tag] not in values)
            ):
                geom_type = Polygon
                break

    # create the way geometry from its constituent nodes' coordinates
    try:
        return geom_type(node_coords[node] for node in way_nodes)
    except (GEOSException, KeyError, ValueError) as e:
        msg = f"Could not build geometry of way {way_id}: {e!r}"
        utils.log(msg, level=lg.WARNING)
        return geom_type()

    Build a way's geometry from its constituent nodes' coordinates.

    A way can be a LineString (open or closed way) or a Polygon (closed way)
    but multi-geometries and polygons with holes are represented as relations.
    See documentation: https://wiki.openstreetmap.org/wiki/Way#Types_of_ways

    Parameters
    ----------
    way_id
        The way's OSM ID.
    way_nodes
        The way's constituent nodes.
    way_tags
        The way's tags.
    node_coords
        Keyed by OSM node ID with values of `(lat, lon)` coordinate tuples.

    Returns
    -------
    geometry
        The way's geometry.
    
osmnx/features.py