Repository: openlawlibrary/pygls

Issue:
Missing language_id in "class Document"
I need to get language_id to identify source's kind. And there are so many LS need this too, such as [efm](https://github.com/mattn/efm-langserver).

pygls declared "TextDocumentItem" with lanuage_id in "pygls/lsp/types/basic_structures.py", but never use /store language_id.


```python
document = ls.workspace.get_document(params.text_document.uri)
document.source        # √
document.language_id   # ×
```

Comments:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 148cefb..d26b9ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning][semver].
 
 ### Fixed
 
+- `Document` objects now expose a text document's `language_id`
+
 ## [0.12] - 04/07/2022
 
 ### Added
diff --git a/pygls/workspace.py b/pygls/workspace.py
index eb4b631..8e73625 100644
--- a/pygls/workspace.py
+++ b/pygls/workspace.py
@@ -20,7 +20,7 @@ import io
 import logging
 import os
 import re
-from typing import List, Pattern
+from typing import List, Optional, Pattern
 
 from pygls.lsp.types import (NumType, Position, Range, TextDocumentContentChangeEvent,
                              TextDocumentItem, TextDocumentSyncKind,
@@ -160,11 +160,19 @@ def range_to_utf16(lines: List[str], range: Range) -> Range:
 
 class Document(object):
 
-    def __init__(self, uri, source=None, version=None, local=True,
-                 sync_kind=TextDocumentSyncKind.INCREMENTAL):
+    def __init__(
+        self,
+        uri: str,
+        source: Optional[str] = None,
+        version: Optional[NumType] = None,
+        language_id: Optional[str] = None,
+        local: bool = True,
+        sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.INCREMENTAL
+    ):
         self.uri = uri
         self.version = version
         self.path = to_fs_path(uri)
+        self.language_id = language_id
         self.filename = os.path.basename(self.path)
 
         self._local = local
@@ -333,12 +341,20 @@ class Workspace(object):
             for folder in workspace_folders:
                 self.add_folder(folder)
 
-    def _create_document(self,
-                         doc_uri: str,
-                         source: str = None,
-                         version: NumType = None) -> Document:
-        return Document(doc_uri, source=source, version=version,
-                        sync_kind=self._sync_kind)
+    def _create_document(
+        self,
+        doc_uri: str,
+        source: Optional[str] = None,
+        version: Optional[NumType] = None,
+        language_id: Optional[str] = None,
+    ) -> Document:
+        return Document(
+            doc_uri,
+            source=source,
+            version=version,
+            language_id=language_id,
+            sync_kind=self._sync_kind
+        )
 
     def add_folder(self, folder: WorkspaceFolder):
         self._folders[folder.uri] = folder
@@ -372,7 +388,8 @@ class Workspace(object):
         self._docs[doc_uri] = self._create_document(
             doc_uri,
             source=text_document.text,
-            version=text_document.version
+            version=text_document.version,
+            language_id=text_document.language_id,
         )
 
     def remove_document(self, doc_uri: str):


Test patch:
diff --git a/tests/test_language_server.py b/tests/test_language_server.py
index 9f48760..98be7cb 100644
--- a/tests/test_language_server.py
+++ b/tests/test_language_server.py
@@ -84,6 +84,12 @@ def test_bf_text_document_did_open(client_server):
 
     assert len(server.lsp.workspace.documents) == 1
 
+    document = server.workspace.get_document(__file__)
+    assert document.uri == __file__
+    assert document.version == 1
+    assert document.source == "test"
+    assert document.language_id == "python"
+
 
 @pytest.mark.skipif(IS_PYODIDE, reason='threads are not available in pyodide.')
 def test_command_async(client_server):