Пример #1
0
    def test_format_doc_no_pgsql_format(self):
        """
        Test that the format codepath succeeds even if the configuration options aren't defined
        """
        input_text = 'select * from foo where id in (select id from bar);'

        context: RequestContext = utils.MockRequestContext()

        self.mock_workspace_service._configuration = None
        workspace, script_file = self._get_test_workspace(True, input_text)
        self.mock_workspace_service._workspace = workspace
        service: LanguageService = self._init_service()

        format_options = FormattingOptions()
        format_options.insert_spaces = False
        format_params = DocumentFormattingParams()
        format_params.options = format_options
        format_params.text_document = self.default_text_document_id

        # When: I have no useful formatting defaults defined
        service.handle_doc_format_request(context, format_params)

        # Then:
        # ... There should be no changes to the doc
        context.send_response.assert_called_once()
        edits: List[TextEdit] = context.last_response_params
        self.assertTrue(len(edits) > 0)
        self.assert_range_equals(edits[0].range,
                                 Range.from_data(0, 0, 0, len(input_text)))
        self.assertEqual(edits[0].new_text, input_text)
Пример #2
0
    def test_default_completion_items(self):
        """
        Test that the completion handler returns a set of default values
        when not connected to any URI
        """
        # If: The script file exists
        input_text = 'create tab'
        doc_position = TextDocumentPosition.from_dict({
            'text_document': {
                'uri': self.default_uri
            },
            'position': {
                'line': 0,
                'character': 10  # end of 'tab' word
            }
        })
        context: RequestContext = utils.MockRequestContext()
        config = Configuration()
        config.sql.intellisense.enable_intellisense = True
        self.mock_workspace_service._configuration = config
        workspace, script_file = self._get_test_workspace(True, input_text)
        self.mock_workspace_service._workspace = workspace
        service: LanguageService = self._init_service()

        # When: I request completion item
        service.handle_completion_request(context, doc_position)

        # Then:
        # ... An default completion set should be sent over the notification
        context.send_response.assert_called_once()
        completions: List[CompletionItem] = context.last_response_params
        self.assertTrue(len(completions) > 0)
        self.verify_match('TABLE', completions, Range.from_data(0, 7, 0, 10))
Пример #3
0
    def test_get_lines_in_range_invalid_start(self):
        # Setup: Create a script file with a selection of test text
        sf = self._get_test_script_file()

        with self.assertRaises(ValueError):
            # If: I ask for the lines of a file that have an invalid start
            # Then: I should get an exception
            params = Range.from_data(-1, 200, 2, 3)
            sf.get_lines_in_range(params)
Пример #4
0
    def test_get_lines_in_range_valid(self):
        # Setup: Create a script file with a selection of test text
        sf = self._get_test_script_file()

        # If: I ask for the valid lines of the file
        params = Range.from_data(1, 1, 3, 1)
        result = sf.get_lines_in_range(params)

        # Then: I should get a set of lines with the expected result
        expected_result = ['ef', 'ghij', 'k']
        self.assertEqual(result, expected_result)
Пример #5
0
    def test_get_text_in_range_start_of_line(self):
        """Test that get_text_in_range works when the cursor is at the start of a line"""
        sf = self._get_test_script_file()

        # If I get text from a range that covers the entire first line and ends on the second line before any text
        params = Range.from_data(0, 0, 1, 0)
        result = sf.get_text_in_range(params)

        # Then I should get the first line and a line with no content as the result
        expected_result = os.linesep.join(['abc', ''])
        self.assertEqual(result, expected_result)
Пример #6
0
    def send_definition_using_connected_completions(
            self, request_context: RequestContext,
            scriptparseinfo: ScriptParseInfo, params: TextDocumentPosition,
            context: ConnectionContext) -> bool:
        if not context or not context.is_connected:
            return False

        definition_result: DefinitionResult = None
        completer: PGCompleter = context.pgcompleter
        completions: List[Completion] = completer.get_completions(
            scriptparseinfo.document, None)

        if completions:
            word_under_cursor = scriptparseinfo.document.get_word_under_cursor(
            )
            matching_completion = next(
                completion for completion in completions
                if completion.display == word_under_cursor)
            if matching_completion:
                connection = self._connection_service.get_connection(
                    params.text_document.uri, ConnectionType.QUERY)
                scripter_instance = scripter.Scripter(connection)
                object_metadata = ObjectMetadata(
                    None, None, matching_completion.display_meta,
                    matching_completion.display, matching_completion.schema)
                create_script = scripter_instance.script(
                    ScriptOperation.CREATE, object_metadata)

                if create_script:
                    with tempfile.NamedTemporaryFile(
                            mode='wt',
                            delete=False,
                            encoding='utf-8',
                            suffix='.sql',
                            newline=None) as namedfile:
                        namedfile.write(create_script)
                        if namedfile.name:
                            file_uri = "file:///" + namedfile.name.strip('/')
                            location_in_script = Location(
                                file_uri, Range(Position(0, 1), Position(1,
                                                                         1)))
                            definition_result = DefinitionResult(
                                False, None, [
                                    location_in_script,
                                ])

                            request_context.send_response(
                                definition_result.locations)
                            return True

        if definition_result is None:
            request_context.send_response(DefinitionResult(True, '', []))
            return False
Пример #7
0
 def test_get_matches_full_keyword(self):
     """Test get matches on a keyword"""
     # Given a default completion helper
     helper = DefaultCompletionHelper()
     text_range = Range.from_data(1, 1, 1, 2)
     start = 'create'
     # When I match 'create'
     matches: List[CompletionItem] = helper.get_matches(
         start, text_range, False)
     # Then I expect only 1 match
     self.assertEqual(1, len(matches))
     # ... and I expect words to be uppercased
     self.verify_match('CREATE', matches, text_range)
    def test_get_text_selection(self):
        """Text the workspace service's public get_text method when getting a selection of the text of a file"""
        # Set up the service with a file
        workspace_service = WorkspaceService()
        file_uri = 'untitled:Test_file'
        file_text = os.linesep.join(['line1', 'line 2 content', ' line 3 '])
        workspace_service._workspace.open_file(file_uri, file_text)

        # Retrieve the full text of the file and make sure it matches
        selection_range = Range(Position(1, 1), Position(2, 4))
        result_text = workspace_service.get_text(file_uri, selection_range)
        self.assertEqual(result_text,
                         os.linesep.join(['ine 2 content', ' lin']))
Пример #9
0
    def handle_definition_request(
            self, request_context: RequestContext,
            text_document_position: TextDocumentPosition) -> None:
        request_context.send_notification(
            STATUS_CHANGE_NOTIFICATION,
            StatusChangeParams(
                owner_uri=text_document_position.text_document.uri,
                status="DefinitionRequested"))

        def do_send_default_empty_response():
            request_context.send_response([])

        if self.should_skip_intellisense(
                text_document_position.text_document.uri):
            do_send_default_empty_response()
            return

        script_file: ScriptFile = self._workspace_service.workspace.get_file(
            text_document_position.text_document.uri)
        if script_file is None:
            do_send_default_empty_response()
            return

        script_parse_info: ScriptParseInfo = self.get_script_parse_info(
            text_document_position.text_document.uri,
            create_if_not_exists=False)
        if not script_parse_info or not script_parse_info.can_queue():
            do_send_default_empty_response()
            return

        cursor_position: int = len(
            script_file.get_text_in_range(
                Range.from_data(0, 0, text_document_position.position.line,
                                text_document_position.position.character)))
        text: str = script_file.get_all_text()
        script_parse_info.document = Document(text, cursor_position)

        operation = QueuedOperation(
            script_parse_info.connection_key,
            functools.partial(self.send_definition_using_connected_completions,
                              request_context, script_parse_info,
                              text_document_position),
            functools.partial(do_send_default_empty_response))
        self.operations_queue.add_operation(operation)
        request_context.send_notification(
            STATUS_CHANGE_NOTIFICATION,
            StatusChangeParams(
                owner_uri=text_document_position.text_document.uri,
                status="DefinitionRequestCompleted"))
Пример #10
0
 def to_completion_item(cls, completion: Completion,
                        params: TextDocumentPosition) -> CompletionItem:
     key = completion.text
     start_position = LanguageService._get_start_position(
         params.position, completion.start_position)
     text_range = Range(start=start_position, end=params.position)
     kind = DISPLAY_META_MAP.get(completion.display_meta,
                                 CompletionItemKind.Unit)
     completion_item = CompletionItem()
     completion_item.label = key
     completion_item.detail = completion.display
     completion_item.insert_text = key
     completion_item.kind = kind
     completion_item.text_edit = TextEdit.from_data(text_range, key)
     # Add a sort text to put keywords after all other items
     completion_item.sort_text = f'~{key}' if completion_item.kind == CompletionItemKind.Keyword else key
     return completion_item
Пример #11
0
    def test_format_doc_range(self):
        """
        Test that the format document range codepath works as expected
        """
        # If: The script file doesn't exist (there is an empty workspace)
        input_lines: List[str] = [
            'select * from t1',
            'select * from foo where id in (select id from bar);'
        ]
        input_text = '\n'.join(input_lines)
        expected_output = '\n'.join([
            'SELECT *', 'FROM foo', 'WHERE id IN', '\t\t\t\t(SELECT id',
            '\t\t\t\t\tFROM bar);'
        ])

        context: RequestContext = utils.MockRequestContext()
        config = Configuration()
        config.pgsql = PGSQLConfiguration()
        config.pgsql.format.keyword_case = 'upper'
        self.mock_workspace_service._configuration = config
        workspace, script_file = self._get_test_workspace(True, input_text)
        self.mock_workspace_service._workspace = workspace
        service: LanguageService = self._init_service()

        format_options = FormattingOptions()
        format_options.insert_spaces = False
        format_params = DocumentRangeFormattingParams()
        format_params.options = format_options
        format_params.text_document = self.default_text_document_id

        # When: I request format the 2nd line of a document
        format_params.range = Range.from_data(1, 0, 1, len(input_lines[1]))
        service.handle_doc_range_format_request(context, format_params)

        # Then:
        # ... only the 2nd line should be formatted
        context.send_response.assert_called_once()
        edits: List[TextEdit] = context.last_response_params
        self.assertTrue(len(edits) > 0)
        self.assert_range_equals(edits[0].range, format_params.range)
        self.assertEqual(edits[0].new_text, expected_output)
Пример #12
0
    def handle_completion_request(self, request_context: RequestContext,
                                  params: TextDocumentPosition) -> None:
        """
        Lookup available completions when valid completion suggestions are requested.
        Sends an array of CompletionItem objects over the wire
        """
        response = []

        def do_send_default_empty_response():
            request_context.send_response(response)

        script_file: ScriptFile = self._workspace_service.workspace.get_file(
            params.text_document.uri)
        if script_file is None:
            do_send_default_empty_response()
            return

        if self.should_skip_intellisense(script_file.file_uri):
            do_send_default_empty_response()
            return

        script_parse_info: ScriptParseInfo = self.get_script_parse_info(
            params.text_document.uri, create_if_not_exists=False)
        if not script_parse_info or not script_parse_info.can_queue():
            self._send_default_completions(request_context, script_file,
                                           params)
        else:
            cursor_position: int = len(
                script_file.get_text_in_range(
                    Range.from_data(0, 0, params.position.line,
                                    params.position.character)))
            text: str = script_file.get_all_text()
            script_parse_info.document = Document(text, cursor_position)
            operation = QueuedOperation(
                script_parse_info.connection_key,
                functools.partial(self.send_connected_completions,
                                  request_context, script_parse_info, params),
                functools.partial(self._send_default_completions,
                                  request_context, script_file, params))
            self.operations_queue.add_operation(operation)
Пример #13
0
    def test_get_matches_one_char(self):
        """Test get matches on 1 character range"""
        # Given a default completion helper
        helper = DefaultCompletionHelper()
        text_range = Range.from_data(1, 1, 1, 2)
        start = 'c'
        # When I match 'c'
        matches: List[CompletionItem] = helper.get_matches(
            start, text_range, False)
        # Then I expect keywords starting with c to be returned
        self.assertTrue(len(matches) > 0)
        # ... and I expect words to be uppercased
        self.verify_match('CREATE', matches, text_range)
        # ... and I expect keywords starting in d to be skipped
        self.verify_miss('DELETE', matches)

        # and When I match with lowercase
        matches: List[CompletionItem] = helper.get_matches(
            start, text_range, True)
        # then I expect a lowercase result
        self.verify_match('create', matches, text_range)
        self.verify_miss('CREATE', matches)
Пример #14
0
    def test_format_doc(self):
        """
        Test that the format document codepath works as expected
        """
        # If: We have a basic string to be formatted
        input_text = 'select * from foo where id in (select id from bar);'
        # Note: sqlparse always uses '\n\ for line separator even on windows.
        # For now, respecting this behavior and leaving as-is
        expected_output = '\n'.join([
            'SELECT *', 'FROM foo', 'WHERE id IN', '\t\t\t\t(SELECT id',
            '\t\t\t\t\tFROM bar);'
        ])

        context: RequestContext = utils.MockRequestContext()
        config = Configuration()
        config.pgsql = PGSQLConfiguration()
        config.pgsql.format.keyword_case = 'upper'
        self.mock_workspace_service._configuration = config
        workspace, script_file = self._get_test_workspace(True, input_text)
        self.mock_workspace_service._workspace = workspace
        service: LanguageService = self._init_service()

        format_options = FormattingOptions()
        format_options.insert_spaces = False
        format_params = DocumentFormattingParams()
        format_params.options = format_options
        format_params.text_document = self.default_text_document_id

        # When: I request document formatting
        service.handle_doc_format_request(context, format_params)

        # Then:
        # ... The entire document text should be formatted
        context.send_response.assert_called_once()
        edits: List[TextEdit] = context.last_response_params
        self.assertTrue(len(edits) > 0)
        self.assert_range_equals(edits[0].range,
                                 Range.from_data(0, 0, 0, len(input_text)))
        self.assertEqual(edits[0].new_text, expected_output)
Пример #15
0
 def _prepare_edit(self, file: ScriptFile) -> TextEdit:
     file_line_count: int = len(file.file_lines)
     last_char = len(file.file_lines[file_line_count - 1])
     text_range = Range.from_data(0, 0, file_line_count - 1, last_char)
     return TextEdit.from_data(text_range, None)
Пример #16
0
 def to_range(self):
     """Convert the SelectionData object to a workspace service Range object"""
     return Range(Position(self.start_line, self.start_column),
                  Position(self.end_line, self.end_column))