Ejemplo n.º 1
0
    def _find_previous_request(
        self,
        transcript: Transcript,
        # pyre-fixme[11]: Annotation `_LspIdMap` is not defined as a type.
        lsp_id_map: _LspIdMap,
        current_id: str,
    ) -> Optional["_RequestSpec"]:
        previous_transcript_entries = itertools.takewhile(
            lambda kv: kv[0] != current_id, transcript.items())
        previous_request_entries = [
            entry.sent for _id, entry in previous_transcript_entries
            if entry.sent is not None
            and LspCommandProcessor._is_request(entry.sent)
        ]
        if previous_request_entries:
            previous_request_lsp_id = previous_request_entries[-1]["id"]
        else:
            return None

        [corresponding_request] = [
            request for request, lsp_id in lsp_id_map.items()
            if lsp_id == previous_request_lsp_id
        ]
        assert isinstance(
            corresponding_request, _RequestSpec
        ), "We should have identified a client-to-server request at this point"
        return corresponding_request
Ejemplo n.º 2
0
    def _find_ignored_transcript_ids(self, transcript: Transcript) -> Iterable[str]:
        for transcript_id, entry in transcript.items():
            if (
                entry.received is not None
                and "id" not in entry.received
                and entry.received.get("method") in self._ignored_notification_methods
            ):
                yield transcript_id

            if (
                entry.received is not None
                and "id" not in entry.received
                and self._ignore_status_diagnostics
                and entry.received["method"] == "textDocument/publishDiagnostics"
                and entry.received["params"].get("isStatusFB")
            ):
                yield transcript_id

            if (
                entry.received is not None
                and "id" in entry.received
                and "method" in entry.received
                and "params" in entry.received
                and (entry.received["method"], entry.received["params"])
                in self._ignored_requests
            ):
                yield transcript_id
Ejemplo n.º 3
0
 def _find_ignored_transcript_ids(self, transcript: Transcript) -> Iterable[str]:
     for transcript_id, entry in transcript.items():
         if (
             entry.received is not None
             and entry.received.get("method") in self._ignored_notification_methods
         ):
             yield transcript_id
Ejemplo n.º 4
0
    def _find_ignored_transcript_ids(self,
                                     transcript: Transcript) -> Iterable[str]:
        for transcript_id, entry in transcript.items():
            if (entry.received is not None and "id" not in entry.received
                    and entry.received.get("method")
                    in self._ignored_notification_methods):
                yield transcript_id

            if (entry.received is not None and "id" in entry.received
                    and "method" in entry.received
                    and "params" in entry.received
                    and (entry.received["method"], entry.received["params"])
                    in self._ignored_requests):
                yield transcript_id
Ejemplo n.º 5
0
    def _flag_unhandled_messages(
        self,
        handled_entries: AbstractSet[str],
        variables: VariableMap,
        transcript: Transcript,
        # pyre-fixme[11]: Annotation `_LspIdMap` is not defined as a type.
        lsp_id_map: _LspIdMap,
    ) -> Iterable["_ErrorDescription"]:
        for transcript_id, entry in transcript.items():
            if transcript_id in handled_entries:
                continue

            received = entry.received
            if received is None:
                continue

            if entry.sent is not None:
                # We received a request and responded to it.
                continue

            method = received["method"]
            params = received["params"]
            payload = self._pretty_print_snippet(received)
            if "id" in received:
                description = f"""\
An unexpected request of type {method!r} was sent by the language server.
Here is the request payload:

{payload}
"""
                at_nocommit = "@" + "nocommit"
                remediation = f"""\
1) If this was unexpected, then the language server is buggy and should be
fixed.

2) If all requests of type {method!r} with theses params should be ignored,
add this directive anywhere in your test:

    .{self.ignore_requests.__name__}(method={method!r}, params={params!r})

3) To handle this request, add this directive to your test to wait for it and
respond to it before proceeding:

    .{self.wait_for_server_request.__name__}(
        method={method!r},
        params={params!r},
        result={{
            "{at_nocommit}": "fill in request data here",
        }},
    )
"""
            else:
                if any(
                        isinstance(message, _WaitForNotificationSpec)
                        and message.method == method and
                        interpolate_variables(payload=message.params,
                                              variables=variables) == params
                        for message in self._messages):
                    # This was a notification we we explicitly waiting for, so skip
                    # it.
                    continue

                uninterpolated_params = uninterpolate_variables(
                    payload=params, variables=variables)
                description = f"""\
An unexpected notification of type {method!r} was sent by the language server.
Here is the notification payload:

{payload}
"""
                remediation = f"""\
1) If this was unexpected, then the language server is buggy and should be
fixed.

2) If all notifications of type {method!r} should be ignored, add this directive
anywhere in your test:

    .{self.ignore_notifications.__name__}(method={method!r})

3) If this single instance of the notification was expected, add this directive
to your test to wait for it before proceeding:

    .{self.wait_for_notification.__name__}(
        method={method!r},
        params={uninterpolated_params!r},
    )
"""

            previous_request = self._find_previous_request(
                transcript, lsp_id_map, current_id=transcript_id)
            if previous_request is not None:
                request_context = self._get_context_for_call_site_info(
                    previous_request.call_site_info)
            else:
                request_context = "<no previous request was found>"
            context = f"""\
This was the most recent request issued from the language client before it
received the notification:

{request_context}"""

            yield _ErrorDescription(description=description,
                                    context=context,
                                    remediation=remediation)
Ejemplo n.º 6
0
    def _flag_unhandled_notifications(
        self,
        handled_entries: AbstractSet[str],
        transcript: Transcript,
        lsp_id_map: _LspIdMap,
    ) -> Iterable["_ErrorDescription"]:
        for transcript_id, entry in transcript.items():
            if transcript_id in handled_entries:
                continue

            received = entry.received
            if received is None:
                continue

            if entry.sent is not None:
                # We received a request and responded it it.
                continue

            method = received["method"]
            params = received["params"]
            payload = self._pretty_print_snippet(received)
            if "id" in received:
                description = f"""\
An unexpected request of type {method!r} was sent by the language server.
Here is the request payload:

{payload}
"""
                at_nocommit = "@" + "nocommit"
                remediation = f"""\
1) If this was unexpected, then the language server is buggy and should be
fixed.

2) To handle this request, add this directive to your test to wait for it and
respond to it before proceeding:

    .{self.wait_for_server_request.__name__}(
        method={method!r},
        params={params!r},
        result={{
            "{at_nocommit}": "fill in request data here",
        }},
    )
"""
            else:
                description = f"""\
An unexpected notification of type {method!r} was sent by the language server.
Here is the notification payload:

{payload}
"""
                remediation = f"""\
1) If this was unexpected, then the language server is buggy and should be
fixed.

2) If all notifications of type {method!r} should be ignored, add this directive
anywhere in your test:

    .{self.ignore_notifications.__name__}(method={method!r})

3) If this single instance of the notification was expected, add this directive
to your test to wait for it before proceeding:

    .{self.wait_for_notification.__name__}(
        method={method!r},
        params={params!r},
    )
"""

            previous_request = self._find_previous_request(
                transcript, lsp_id_map, current_id=transcript_id)
            if previous_request is not None:
                request_context = self._get_context_for_traceback(
                    previous_request.traceback)
            else:
                request_context = "<no previous request was found>"
            context = f"""\
This was the most recent request issued from the language client before it
received the notification:

{request_context}"""

            yield _ErrorDescription(description=description,
                                    context=context,
                                    remediation=remediation)