We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Unwanted splitting on dot of the setting keys
**Describe the bug**

In LSP-yaml, the user can specify schema mapping like so:

```
yaml.schemas: {
    "https://json.schemastore.org/composer": "/*"
}
```

This doesn't work in ST because LSP splits the URL key on every dot, creating an object that the server doesn't understand.

**Expected behavior**

Should send the value of the `yaml.schemas` object without altering it

**Additional context**

I'm not sure how VSCode manages to handle it but I would guess it is somewhat taking into consideration the schema itself. We could try to check that first.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `plugin/core/collections.py`
Content:
```
1 """
2 Module with additional collections.
3 """
4 from .typing import Optional, Dict, Any, Generator
5 from copy import deepcopy
6 import sublime
7 
8 
9 class DottedDict:
10 
11     __slots__ = ('_d',)
12 
13     def __init__(self, d: Optional[Dict[str, Any]] = None) -> None:
14         """
15         Construct a DottedDict, optionally from an existing dictionary.
16 
17         :param      d:    An existing dictionary.
18         """
19         self._d = {}  # type: Dict[str, Any]
20         if d is not None:
21             self.update(d)
22 
23     @classmethod
24     def from_base_and_override(cls, base: "DottedDict", override: Optional[Dict[str, Any]]) -> "DottedDict":
25         result = DottedDict(base.copy())
26         if override:
27             result.update(override)
28         return result
29 
30     def get(self, path: Optional[str] = None) -> Any:
31         """
32         Get a value from the dictionary.
33 
34         :param      path:  The path, e.g. foo.bar.baz, or None.
35 
36         :returns:   The value stored at the path, or None if it doesn't exist.
37                     Note that this cannot distinguish between None values and
38                     paths that don't exist. If the path is None, returns the
39                     entire dictionary.
40         """
41         if path is None:
42             return self._d
43         current = self._d  # type: Any
44         keys = path.split('.')
45         for key in keys:
46             if isinstance(current, dict):
47                 current = current.get(key)
48             else:
49                 return None
50         return current
51 
52     def walk(self, path: str) -> Generator[Any, None, None]:
53         current = self._d  # type: Any
54         keys = path.split('.')
55         for key in keys:
56             if isinstance(current, dict):
57                 current = current.get(key)
58                 yield current
59             else:
60                 yield None
61                 return
62 
63     def set(self, path: str, value: Any) -> None:
64         """
65         Set a value in the dictionary.
66 
67         :param      path:   The path, e.g. foo.bar.baz
68         :param      value:  The value
69         """
70         current = self._d
71         keys = path.split('.')
72         for i in range(0, len(keys) - 1):
73             key = keys[i]
74             next_current = current.get(key)
75             if not isinstance(next_current, dict):
76                 next_current = {}
77                 current[key] = next_current
78             current = next_current
79         current[keys[-1]] = value
80 
81     def remove(self, path: str) -> None:
82         """
83         Remove a key from the dictionary.
84 
85         :param      path:  The path, e.g. foo.bar.baz
86         """
87         current = self._d
88         keys = path.split('.')
89         for i in range(0, len(keys) - 1):
90             key = keys[i]
91             next_current = current.get(key)
92             if not isinstance(next_current, dict):
93                 return
94             current = next_current
95         current.pop(keys[-1], None)
96 
97     def copy(self, path: Optional[str] = None) -> Any:
98         """
99         Get a copy of the value from the dictionary or copy of whole dictionary.
100 
101         :param      path:  The path, e.g. foo.bar.baz, or None.
102 
103         :returns:   A copy of the value stored at the path, or None if it doesn't exist.
104                     Note that this cannot distinguish between None values and
105                     paths that don't exist. If the path is None, returns a copy of the
106                     entire dictionary.
107         """
108         return deepcopy(self.get(path))
109 
110     def __bool__(self) -> bool:
111         """
112         If this collection has at least one key-value pair, return True, else return False.
113         """
114         return bool(self._d)
115 
116     def __contains__(self, path: str) -> bool:
117         value = self.get(path)
118         return value is not None and value is not False
119 
120     def clear(self) -> None:
121         """
122         Remove all key-value pairs.
123         """
124         self._d.clear()
125 
126     def assign(self, d: Dict[str, Any]) -> None:
127         """
128         Overwrites the old stored dictionary with a fresh new dictionary.
129 
130         :param      d:    The new dictionary to store
131         """
132         self._d = d
133 
134     def update(self, d: Dict[str, Any]) -> None:
135         """
136         Overwrite and/or add new key-value pairs to the collection.
137 
138         :param      d:    The overriding dictionary. Can contain nested dictionaries.
139         """
140         for key, value in d.items():
141             if isinstance(value, dict):
142                 self._update_recursive(value, key)
143             else:
144                 self.set(key, value)
145 
146     def get_resolved(self, variables: Dict[str, str]) -> Dict[str, Any]:
147         """
148         Resolve a DottedDict that may potentially contain template variables like $folder.
149 
150         :param      variables:  The variables
151 
152         :returns:   A copy of the underlying dictionary, but with the variables replaced
153         """
154         return sublime.expand_variables(self._d, variables)
155 
156     def _update_recursive(self, current: Dict[str, Any], prefix: str) -> None:
157         if not current:
158             return self.set(prefix, current)
159         for key, value in current.items():
160             path = "{}.{}".format(prefix, key)
161             if isinstance(value, dict):
162                 self._update_recursive(value, path)
163             else:
164                 self.set(path, value)
165 
166     def __repr__(self) -> str:
167         return "{}({})".format(self.__class__.__name__, repr(self._d))
168 
169     def __eq__(self, other: Any) -> bool:
170         if not isinstance(other, DottedDict):
171             return False
172         return self._d == other._d
173
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/plugin/core/collections.py b/plugin/core/collections.py
--- a/plugin/core/collections.py
+++ b/plugin/core/collections.py
@@ -113,7 +113,9 @@
         """
         return bool(self._d)
 
-    def __contains__(self, path: str) -> bool:
+    def __contains__(self, path: object) -> bool:
+        if not isinstance(path, str):
+            return False
         value = self.get(path)
         return value is not None and value is not False
 
@@ -154,7 +156,7 @@
         return sublime.expand_variables(self._d, variables)
 
     def _update_recursive(self, current: Dict[str, Any], prefix: str) -> None:
-        if not current:
+        if not current or any(filter(lambda key: isinstance(key, str) and (":" in key or "/" in key), current.keys())):
             return self.set(prefix, current)
         for key, value in current.items():
             path = "{}.{}".format(prefix, key)

{"golden_diff": "diff --git a/plugin/core/collections.py b/plugin/core/collections.py\n--- a/plugin/core/collections.py\n+++ b/plugin/core/collections.py\n@@ -113,7 +113,9 @@\n         \"\"\"\n         return bool(self._d)\n \n-    def __contains__(self, path: str) -> bool:\n+    def __contains__(self, path: object) -> bool:\n+        if not isinstance(path, str):\n+            return False\n         value = self.get(path)\n         return value is not None and value is not False\n \n@@ -154,7 +156,7 @@\n         return sublime.expand_variables(self._d, variables)\n \n     def _update_recursive(self, current: Dict[str, Any], prefix: str) -> None:\n-        if not current:\n+        if not current or any(filter(lambda key: isinstance(key, str) and (\":\" in key or \"/\" in key), current.keys())):\n             return self.set(prefix, current)\n         for key, value in current.items():\n             path = \"{}.{}\".format(prefix, key)\n", "issue": "Unwanted splitting on dot of the setting keys\n**Describe the bug**\r\n\r\nIn LSP-yaml, the user can specify schema mapping like so:\r\n\r\n```\r\nyaml.schemas: {\r\n    \"https://json.schemastore.org/composer\": \"/*\"\r\n}\r\n```\r\n\r\nThis doesn't work in ST because LSP splits the URL key on every dot, creating an object that the server doesn't understand.\r\n\r\n**Expected behavior**\r\n\r\nShould send the value of the `yaml.schemas` object without altering it\r\n\r\n**Additional context**\r\n\r\nI'm not sure how VSCode manages to handle it but I would guess it is somewhat taking into consideration the schema itself. We could try to check that first.\n", "before_files": [{"content": "\"\"\"\nModule with additional collections.\n\"\"\"\nfrom .typing import Optional, Dict, Any, Generator\nfrom copy import deepcopy\nimport sublime\n\n\nclass DottedDict:\n\n    __slots__ = ('_d',)\n\n    def __init__(self, d: Optional[Dict[str, Any]] = None) -> None:\n        \"\"\"\n        Construct a DottedDict, optionally from an existing dictionary.\n\n        :param      d:    An existing dictionary.\n        \"\"\"\n        self._d = {}  # type: Dict[str, Any]\n        if d is not None:\n            self.update(d)\n\n    @classmethod\n    def from_base_and_override(cls, base: \"DottedDict\", override: Optional[Dict[str, Any]]) -> \"DottedDict\":\n        result = DottedDict(base.copy())\n        if override:\n            result.update(override)\n        return result\n\n    def get(self, path: Optional[str] = None) -> Any:\n        \"\"\"\n        Get a value from the dictionary.\n\n        :param      path:  The path, e.g. foo.bar.baz, or None.\n\n        :returns:   The value stored at the path, or None if it doesn't exist.\n                    Note that this cannot distinguish between None values and\n                    paths that don't exist. If the path is None, returns the\n                    entire dictionary.\n        \"\"\"\n        if path is None:\n            return self._d\n        current = self._d  # type: Any\n        keys = path.split('.')\n        for key in keys:\n            if isinstance(current, dict):\n                current = current.get(key)\n            else:\n                return None\n        return current\n\n    def walk(self, path: str) -> Generator[Any, None, None]:\n        current = self._d  # type: Any\n        keys = path.split('.')\n        for key in keys:\n            if isinstance(current, dict):\n                current = current.get(key)\n                yield current\n            else:\n                yield None\n                return\n\n    def set(self, path: str, value: Any) -> None:\n        \"\"\"\n        Set a value in the dictionary.\n\n        :param      path:   The path, e.g. foo.bar.baz\n        :param      value:  The value\n        \"\"\"\n        current = self._d\n        keys = path.split('.')\n        for i in range(0, len(keys) - 1):\n            key = keys[i]\n            next_current = current.get(key)\n            if not isinstance(next_current, dict):\n                next_current = {}\n                current[key] = next_current\n            current = next_current\n        current[keys[-1]] = value\n\n    def remove(self, path: str) -> None:\n        \"\"\"\n        Remove a key from the dictionary.\n\n        :param      path:  The path, e.g. foo.bar.baz\n        \"\"\"\n        current = self._d\n        keys = path.split('.')\n        for i in range(0, len(keys) - 1):\n            key = keys[i]\n            next_current = current.get(key)\n            if not isinstance(next_current, dict):\n                return\n            current = next_current\n        current.pop(keys[-1], None)\n\n    def copy(self, path: Optional[str] = None) -> Any:\n        \"\"\"\n        Get a copy of the value from the dictionary or copy of whole dictionary.\n\n        :param      path:  The path, e.g. foo.bar.baz, or None.\n\n        :returns:   A copy of the value stored at the path, or None if it doesn't exist.\n                    Note that this cannot distinguish between None values and\n                    paths that don't exist. If the path is None, returns a copy of the\n                    entire dictionary.\n        \"\"\"\n        return deepcopy(self.get(path))\n\n    def __bool__(self) -> bool:\n        \"\"\"\n        If this collection has at least one key-value pair, return True, else return False.\n        \"\"\"\n        return bool(self._d)\n\n    def __contains__(self, path: str) -> bool:\n        value = self.get(path)\n        return value is not None and value is not False\n\n    def clear(self) -> None:\n        \"\"\"\n        Remove all key-value pairs.\n        \"\"\"\n        self._d.clear()\n\n    def assign(self, d: Dict[str, Any]) -> None:\n        \"\"\"\n        Overwrites the old stored dictionary with a fresh new dictionary.\n\n        :param      d:    The new dictionary to store\n        \"\"\"\n        self._d = d\n\n    def update(self, d: Dict[str, Any]) -> None:\n        \"\"\"\n        Overwrite and/or add new key-value pairs to the collection.\n\n        :param      d:    The overriding dictionary. Can contain nested dictionaries.\n        \"\"\"\n        for key, value in d.items():\n            if isinstance(value, dict):\n                self._update_recursive(value, key)\n            else:\n                self.set(key, value)\n\n    def get_resolved(self, variables: Dict[str, str]) -> Dict[str, Any]:\n        \"\"\"\n        Resolve a DottedDict that may potentially contain template variables like $folder.\n\n        :param      variables:  The variables\n\n        :returns:   A copy of the underlying dictionary, but with the variables replaced\n        \"\"\"\n        return sublime.expand_variables(self._d, variables)\n\n    def _update_recursive(self, current: Dict[str, Any], prefix: str) -> None:\n        if not current:\n            return self.set(prefix, current)\n        for key, value in current.items():\n            path = \"{}.{}\".format(prefix, key)\n            if isinstance(value, dict):\n                self._update_recursive(value, path)\n            else:\n                self.set(path, value)\n\n    def __repr__(self) -> str:\n        return \"{}({})\".format(self.__class__.__name__, repr(self._d))\n\n    def __eq__(self, other: Any) -> bool:\n        if not isinstance(other, DottedDict):\n            return False\n        return self._d == other._d\n", "path": "plugin/core/collections.py"}], "after_files": [{"content": "\"\"\"\nModule with additional collections.\n\"\"\"\nfrom .typing import Optional, Dict, Any, Generator\nfrom copy import deepcopy\nimport sublime\n\n\nclass DottedDict:\n\n    __slots__ = ('_d',)\n\n    def __init__(self, d: Optional[Dict[str, Any]] = None) -> None:\n        \"\"\"\n        Construct a DottedDict, optionally from an existing dictionary.\n\n        :param      d:    An existing dictionary.\n        \"\"\"\n        self._d = {}  # type: Dict[str, Any]\n        if d is not None:\n            self.update(d)\n\n    @classmethod\n    def from_base_and_override(cls, base: \"DottedDict\", override: Optional[Dict[str, Any]]) -> \"DottedDict\":\n        result = DottedDict(base.copy())\n        if override:\n            result.update(override)\n        return result\n\n    def get(self, path: Optional[str] = None) -> Any:\n        \"\"\"\n        Get a value from the dictionary.\n\n        :param      path:  The path, e.g. foo.bar.baz, or None.\n\n        :returns:   The value stored at the path, or None if it doesn't exist.\n                    Note that this cannot distinguish between None values and\n                    paths that don't exist. If the path is None, returns the\n                    entire dictionary.\n        \"\"\"\n        if path is None:\n            return self._d\n        current = self._d  # type: Any\n        keys = path.split('.')\n        for key in keys:\n            if isinstance(current, dict):\n                current = current.get(key)\n            else:\n                return None\n        return current\n\n    def walk(self, path: str) -> Generator[Any, None, None]:\n        current = self._d  # type: Any\n        keys = path.split('.')\n        for key in keys:\n            if isinstance(current, dict):\n                current = current.get(key)\n                yield current\n            else:\n                yield None\n                return\n\n    def set(self, path: str, value: Any) -> None:\n        \"\"\"\n        Set a value in the dictionary.\n\n        :param      path:   The path, e.g. foo.bar.baz\n        :param      value:  The value\n        \"\"\"\n        current = self._d\n        keys = path.split('.')\n        for i in range(0, len(keys) - 1):\n            key = keys[i]\n            next_current = current.get(key)\n            if not isinstance(next_current, dict):\n                next_current = {}\n                current[key] = next_current\n            current = next_current\n        current[keys[-1]] = value\n\n    def remove(self, path: str) -> None:\n        \"\"\"\n        Remove a key from the dictionary.\n\n        :param      path:  The path, e.g. foo.bar.baz\n        \"\"\"\n        current = self._d\n        keys = path.split('.')\n        for i in range(0, len(keys) - 1):\n            key = keys[i]\n            next_current = current.get(key)\n            if not isinstance(next_current, dict):\n                return\n            current = next_current\n        current.pop(keys[-1], None)\n\n    def copy(self, path: Optional[str] = None) -> Any:\n        \"\"\"\n        Get a copy of the value from the dictionary or copy of whole dictionary.\n\n        :param      path:  The path, e.g. foo.bar.baz, or None.\n\n        :returns:   A copy of the value stored at the path, or None if it doesn't exist.\n                    Note that this cannot distinguish between None values and\n                    paths that don't exist. If the path is None, returns a copy of the\n                    entire dictionary.\n        \"\"\"\n        return deepcopy(self.get(path))\n\n    def __bool__(self) -> bool:\n        \"\"\"\n        If this collection has at least one key-value pair, return True, else return False.\n        \"\"\"\n        return bool(self._d)\n\n    def __contains__(self, path: object) -> bool:\n        if not isinstance(path, str):\n            return False\n        value = self.get(path)\n        return value is not None and value is not False\n\n    def clear(self) -> None:\n        \"\"\"\n        Remove all key-value pairs.\n        \"\"\"\n        self._d.clear()\n\n    def assign(self, d: Dict[str, Any]) -> None:\n        \"\"\"\n        Overwrites the old stored dictionary with a fresh new dictionary.\n\n        :param      d:    The new dictionary to store\n        \"\"\"\n        self._d = d\n\n    def update(self, d: Dict[str, Any]) -> None:\n        \"\"\"\n        Overwrite and/or add new key-value pairs to the collection.\n\n        :param      d:    The overriding dictionary. Can contain nested dictionaries.\n        \"\"\"\n        for key, value in d.items():\n            if isinstance(value, dict):\n                self._update_recursive(value, key)\n            else:\n                self.set(key, value)\n\n    def get_resolved(self, variables: Dict[str, str]) -> Dict[str, Any]:\n        \"\"\"\n        Resolve a DottedDict that may potentially contain template variables like $folder.\n\n        :param      variables:  The variables\n\n        :returns:   A copy of the underlying dictionary, but with the variables replaced\n        \"\"\"\n        return sublime.expand_variables(self._d, variables)\n\n    def _update_recursive(self, current: Dict[str, Any], prefix: str) -> None:\n        if not current or any(filter(lambda key: isinstance(key, str) and (\":\" in key or \"/\" in key), current.keys())):\n            return self.set(prefix, current)\n        for key, value in current.items():\n            path = \"{}.{}\".format(prefix, key)\n            if isinstance(value, dict):\n                self._update_recursive(value, path)\n            else:\n                self.set(path, value)\n\n    def __repr__(self) -> str:\n        return \"{}({})\".format(self.__class__.__name__, repr(self._d))\n\n    def __eq__(self, other: Any) -> bool:\n        if not isinstance(other, DottedDict):\n            return False\n        return self._d == other._d\n", "path": "plugin/core/collections.py"}]}