diff --git a/src/python/diff3_analysis.ipynb b/src/python/diff3_analysis.ipynb
index 558935f300..409ad5d373 100644
--- a/src/python/diff3_analysis.ipynb
+++ b/src/python/diff3_analysis.ipynb
@@ -2,28 +2,105 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "fasterxml/jackson-core : Cloning repo\n",
+ "fasterxml/jackson-core : Finished cloning\n",
+ "fasterxml/jackson-core : Finished cloning\n",
+ "Checking out left294f761da4b185c997d6f19d0753711b702fe702\n",
+ "Checking out right2cd126e3f8cbf8fee29f7a21f6c0c5c34fa63344\n",
+ "Found base shaf554808f2285ab7fa68a7b830e33417712ce4a26\n",
+ "\n",
+ "fasterxml/jackson-core : Cloning repo\n",
+ "fasterxml/jackson-core : Finished cloning\n",
+ "fasterxml/jackson-core : Finished cloning\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Switched to branch 'TEMP_LEFT_BRANCH'\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Running: git merge --no-edit -s ort TEMP_RIGHT_BRANCH\n",
+ "Auto-merging pom.xml\n",
+ "CONFLICT (content): Merge conflict in pom.xml\n",
+ "Auto-merging release-notes/VERSION\n",
+ "CONFLICT (content): Merge conflict in release-notes/VERSION\n",
+ "Automatic merge failed; fix conflicts and then commit the result.\n",
+ "Conflict\n",
+ "\n",
+ "fasterxml/jackson-core : Cloning repo\n",
+ "fasterxml/jackson-core : Finished cloning\n",
+ "fasterxml/jackson-core : Finished cloning\n",
+ "Diff results saved to ./merge_conflict_analysis_diffs/809/gitmerge_ort/diff_pom.xml.txt\n",
+ "Diff results saved to ./merge_conflict_analysis_diffs/809/gitmerge_ort/diff_VERSION.txt\n",
+ "fasterxml/jackson-core : Cloning repo\n",
+ "fasterxml/jackson-core : Finished cloning\n"
+ ]
+ },
+ {
+ "ename": "KeyboardInterrupt",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[1], line 31\u001b[0m\n\u001b[1;32m 29\u001b[0m repo_output_dir \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(base_output_dir, \u001b[38;5;28mstr\u001b[39m(row_num), merge_tool)\n\u001b[1;32m 30\u001b[0m os\u001b[38;5;241m.\u001b[39mmakedirs(repo_output_dir, exist_ok\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[0;32m---> 31\u001b[0m \u001b[43mdiff3_analysis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmerge_tool\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrow_num\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrepo_output_dir\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m~/Documents/GitHub/AST-Merging-Ben-Analysis/src/python/diff3_analysis.py:38\u001b[0m, in \u001b[0;36mdiff3_analysis\u001b[0;34m(merge_tool, results_index, repo_output_dir)\u001b[0m\n\u001b[1;32m 35\u001b[0m repo_name \u001b[38;5;241m=\u001b[39m df\u001b[38;5;241m.\u001b[39miloc[results_index][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrepository\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 37\u001b[0m script \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m../scripts/merge_tools/\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m merge_tool \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.sh\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 38\u001b[0m repo \u001b[38;5;241m=\u001b[39m \u001b[43mclone_repo_to_path\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 39\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m./repos/merge_attempt\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 40\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# Return a Git-Python repo object\u001b[39;00m\n\u001b[1;32m 41\u001b[0m repo\u001b[38;5;241m.\u001b[39mremote()\u001b[38;5;241m.\u001b[39mfetch()\n\u001b[1;32m 42\u001b[0m left_sha \u001b[38;5;241m=\u001b[39m df\u001b[38;5;241m.\u001b[39miloc[results_index][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mleft\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n",
+ "File \u001b[0;32m~/Documents/GitHub/AST-Merging-Ben-Analysis/src/python/repo.py:77\u001b[0m, in \u001b[0;36mclone_repo_to_path\u001b[0;34m(repo_slug, path)\u001b[0m\n\u001b[1;32m 75\u001b[0m \u001b[38;5;28mprint\u001b[39m(repo_slug, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m : Finished cloning\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 76\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 77\u001b[0m repo \u001b[38;5;241m=\u001b[39m \u001b[43mgit\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrepo\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mRepo\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclone_from\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgithub_url\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrepo_dir\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 78\u001b[0m \u001b[38;5;28mprint\u001b[39m(repo_slug, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m : Finished cloning\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 79\u001b[0m repo\u001b[38;5;241m.\u001b[39mremote()\u001b[38;5;241m.\u001b[39mfetch()\n",
+ "File \u001b[0;32m~/miniconda/envs/research/lib/python3.8/site-packages/git/repo/base.py:1328\u001b[0m, in \u001b[0;36mRepo.clone_from\u001b[0;34m(cls, url, to_path, progress, env, multi_options, allow_unsafe_protocols, allow_unsafe_options, **kwargs)\u001b[0m\n\u001b[1;32m 1326\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m env \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 1327\u001b[0m git\u001b[38;5;241m.\u001b[39mupdate_environment(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39menv)\n\u001b[0;32m-> 1328\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_clone\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1329\u001b[0m \u001b[43m \u001b[49m\u001b[43mgit\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1330\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1331\u001b[0m \u001b[43m \u001b[49m\u001b[43mto_path\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1332\u001b[0m \u001b[43m \u001b[49m\u001b[43mGitCmdObjectDB\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1333\u001b[0m \u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1334\u001b[0m \u001b[43m \u001b[49m\u001b[43mmulti_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1335\u001b[0m \u001b[43m \u001b[49m\u001b[43mallow_unsafe_protocols\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mallow_unsafe_protocols\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1336\u001b[0m \u001b[43m \u001b[49m\u001b[43mallow_unsafe_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mallow_unsafe_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1337\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1338\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m~/miniconda/envs/research/lib/python3.8/site-packages/git/repo/base.py:1232\u001b[0m, in \u001b[0;36mRepo._clone\u001b[0;34m(cls, git, url, path, odb_default_type, progress, multi_options, allow_unsafe_protocols, allow_unsafe_options, **kwargs)\u001b[0m\n\u001b[1;32m 1224\u001b[0m handle_process_output(\n\u001b[1;32m 1225\u001b[0m proc,\n\u001b[1;32m 1226\u001b[0m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1229\u001b[0m decode_streams\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m 1230\u001b[0m )\n\u001b[1;32m 1231\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1232\u001b[0m (stdout, stderr) \u001b[38;5;241m=\u001b[39m \u001b[43mproc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcommunicate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1233\u001b[0m cmdline \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mgetattr\u001b[39m(proc, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124margs\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 1234\u001b[0m cmdline \u001b[38;5;241m=\u001b[39m remove_password_if_present(cmdline)\n",
+ "File \u001b[0;32m~/miniconda/envs/research/lib/python3.8/subprocess.py:1028\u001b[0m, in \u001b[0;36mPopen.communicate\u001b[0;34m(self, input, timeout)\u001b[0m\n\u001b[1;32m 1025\u001b[0m endtime \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 1027\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1028\u001b[0m stdout, stderr \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_communicate\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mendtime\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1029\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[1;32m 1030\u001b[0m \u001b[38;5;66;03m# https://bugs.python.org/issue25942\u001b[39;00m\n\u001b[1;32m 1031\u001b[0m \u001b[38;5;66;03m# See the detailed comment in .wait().\u001b[39;00m\n\u001b[1;32m 1032\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m timeout \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
+ "File \u001b[0;32m~/miniconda/envs/research/lib/python3.8/subprocess.py:1884\u001b[0m, in \u001b[0;36mPopen._communicate\u001b[0;34m(self, input, endtime, orig_timeout)\u001b[0m\n\u001b[1;32m 1877\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_timeout(endtime, orig_timeout,\n\u001b[1;32m 1878\u001b[0m stdout, stderr,\n\u001b[1;32m 1879\u001b[0m skip_check_and_raise\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[1;32m 1880\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m( \u001b[38;5;66;03m# Impossible :)\u001b[39;00m\n\u001b[1;32m 1881\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_check_timeout(..., skip_check_and_raise=True) \u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 1882\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfailed to raise TimeoutExpired.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m-> 1884\u001b[0m ready \u001b[38;5;241m=\u001b[39m \u001b[43mselector\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mselect\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1885\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_timeout(endtime, orig_timeout, stdout, stderr)\n\u001b[1;32m 1887\u001b[0m \u001b[38;5;66;03m# XXX Rewrite these to use non-blocking I/O on the file\u001b[39;00m\n\u001b[1;32m 1888\u001b[0m \u001b[38;5;66;03m# objects; they are no longer using C stdio!\u001b[39;00m\n",
+ "File \u001b[0;32m~/miniconda/envs/research/lib/python3.8/selectors.py:415\u001b[0m, in \u001b[0;36m_PollLikeSelector.select\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 413\u001b[0m ready \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 414\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 415\u001b[0m fd_event_list \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_selector\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpoll\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 416\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mInterruptedError\u001b[39;00m:\n\u001b[1;32m 417\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m ready\n",
+ "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
+ ]
+ }
+ ],
"source": [
- "row_num = 1444\n",
- "merge_tool = \"gitmerge_ort\"\n",
- "# merge_tool = \"gitmerge_ort_adjacent\"\n",
- "# merge_tool = \"gitmerge_ort_ignorespace\"\n",
- "# merge_tool = \"gitmerge_ort_imports\"\n",
- "# merge_tool = \"gitmerge_ort_imports_ignorespace\"\n",
- "# merge_tool = \"gitmerge_resolve\"\n",
- "# merge_tool = \"gitmerge_recursive_histogram\"\n",
- "# merge_tool = \"gitmerge_recursive_ignorespace\"\n",
- "# merge_tool = \"gitmerge_recursive_minimal\"\t\n",
- "# merge_tool = \"gitmerge_recursive_myers\"\n",
- "# merge_tool = \"gitmerge_recursive_patience\"\n",
- "# merge_tool = \"git_hires_merge\"\n",
- "# merge_tool = \"spork\"\n",
- "# merge_tool = \"intellimerge\"\n",
- "\n",
"from diff3_analysis import diff3_analysis\n",
- "diff3_analysis(merge_tool, row_num)"
+ "import os\n",
+ "\n",
+ "row_nums = [\n",
+ " 582, 427, 930, 70, 128, 1444, 1177, 849, 1425, 1642, 1897, 862, 943, 1442, 1120,\n",
+ " 111, 693, 535, 354, 530, 845, 654, 921, 464, 1006, 707, 485, 1928, 809, 1329, 65, 1890, 100, 247, 2038, 900\n",
+ "]\n",
+ "\n",
+ "merge_tools = [\"gitmerge_ort\", \n",
+ " \"gitmerge_ort_adjacent\", \n",
+ " \"gitmerge_ort_ignorespace\", \n",
+ " \"gitmerge_ort_imports\", \n",
+ " \"gitmerge_ort_imports_ignorespace\", \n",
+ " \"gitmerge_resolve\",\n",
+ " \"gitmerge_recursive_histogram\", \n",
+ " \"gitmerge_recursive_ignorespace\", \n",
+ " \"gitmerge_recursive_minimal\", \n",
+ " \"gitmerge_recursive_myers\", \n",
+ " \"gitmerge_recursive_patience\",\n",
+ " \"git_hires_merge\",\n",
+ " \"spork\", \n",
+ " \"intellimerge\"]\n",
+ "\n",
+ "# Ensure the base output directory exists\n",
+ "base_output_dir = \"./merge_conflict_analysis_diffs\"\n",
+ "\n",
+ "for row_num in row_nums:\n",
+ " for merge_tool in merge_tools:\n",
+ " # Create a subdirectory for this specific results_index\n",
+ " repo_output_dir = os.path.join(base_output_dir, str(row_num), merge_tool)\n",
+ " os.makedirs(repo_output_dir, exist_ok=True)\n",
+ " diff3_analysis(merge_tool, row_num, repo_output_dir)\n"
]
}
],
diff --git a/src/python/diff3_analysis.py b/src/python/diff3_analysis.py
index b1aeba9123..8acf862db7 100644
--- a/src/python/diff3_analysis.py
+++ b/src/python/diff3_analysis.py
@@ -13,14 +13,15 @@
# pylint: disable-msg=too-many-locals
-def diff3_analysis(merge_tool: str, results_index: int):
+def diff3_analysis(merge_tool: str, results_index: int, repo_output_dir):
"""
Analyzes merge conflicts using the diff3 tool and opens the results in the default text viewer.
Args:
merge_tool (str): The merge tool to be used.
results_index (int): The index of the repository in the results DataFrame.
-
+ repo_output_dir (path): The path of where we want to store the results from the analysis
+
Returns:
None
"""
@@ -29,12 +30,6 @@ def diff3_analysis(merge_tool: str, results_index: int):
# We do this to prevent errors if cloning the same repo into the folder twice
shutil.rmtree("./repos", ignore_errors=True)
- # Ensure the base output directory exists
- base_output_dir = "./merge_conflict_analysis_diffs"
- # Create a subdirectory for this specific results_index
- repo_output_dir = os.path.join(base_output_dir, f"index_{results_index}")
- os.makedirs(repo_output_dir, exist_ok=True)
-
# Retrieve left and right branch from hash in repo
df = pd.read_csv("../../results_greatest_hits/result.csv")
repo_name = df.iloc[results_index]["repository"]
diff --git a/src/python/merge_conflict_analysis_diffs/1006/git_hires_merge/diff_Gson.java.txt b/src/python/merge_conflict_analysis_diffs/1006/git_hires_merge/diff_Gson.java.txt
new file mode 100644
index 0000000000..979214efc7
--- /dev/null
+++ b/src/python/merge_conflict_analysis_diffs/1006/git_hires_merge/diff_Gson.java.txt
@@ -0,0 +1,1124 @@
+====1
+1:19,37c
+ import java.io.EOFException;
+ import java.io.IOException;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.lang.reflect.Type;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.text.DateFormat;
+ import java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicLongArray;
+
+2:18a
+3:18a
+====3
+1:53a
+2:34a
+3:35c
+ import com.google.gson.internal.bind.SerializationDelegatingTypeAdapter;
+====
+1:60a
+2:42,61c
+ import java.io.EOFException;
+ import java.io.IOException;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.lang.reflect.Type;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.text.DateFormat;
+ import java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.Iterator;
+ import java.util.LinkedHashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
+ import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicLongArray;
+3:43,63c
+ import java.io.EOFException;
+ import java.io.IOException;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.lang.reflect.Type;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.text.DateFormat;
+ import java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.Iterator;
+ import java.util.LinkedHashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Objects;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
+ import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicLongArray;
+====3
+1:78c
+2:79c
+ * String json = gson.toJson(target); // serializes target to Json
+3:81c
+ * String json = gson.toJson(target); // serializes target to JSON
+====3
+1:82,86c
+2:83,87c
+ *
If the object that your are serializing/deserializing is a {@code ParameterizedType}
+ * (i.e. contains at least one type parameter and may be an array) then you must use the
+ * {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an
+ * example for serializing and deserializing a {@code ParameterizedType}:
+ *
+3:85,91c
+ *
If the type of the object that you are converting is a {@code ParameterizedType}
+ * (i.e. has at least one type argument, for example {@code List}) then for
+ * deserialization you must use a {@code fromJson} method with {@link Type} or {@link TypeToken}
+ * parameter to specify the parameterized type. For serialization specifying a {@code Type}
+ * or {@code TypeToken} is optional, otherwise Gson will use the runtime type of the object.
+ * {@link TypeToken} is a class provided by Gson which helps creating parameterized types.
+ * Here is an example showing how this can be done:
+====3
+1:88,90c
+2:89,91c
+ * Type listType = new TypeToken<List<String>>() {}.getType();
+ * List<String> target = new LinkedList<String>();
+ * target.add("blah");
+3:93,95c
+ * TypeToken<List<MyType>> listType = new TypeToken<List<MyType>>() {};
+ * List<MyType> target = new LinkedList<MyType>();
+ * target.add(new MyType(1, "abc"));
+====3
+1:93,94c
+2:94,95c
+ * String json = gson.toJson(target, listType);
+ * List<String> target2 = gson.fromJson(json, listType);
+3:98,103c
+ * // For serialization you normally do not have to specify the type, Gson will use
+ * // the runtime type of the objects, however you can also specify it explicitly
+ * String json = gson.toJson(target, listType.getType());
+ *
+ * // But for deserialization you have to specify the type
+ * List<MyType> target2 = gson.fromJson(json, listType);
+====3
+1:97c
+2:98c
+ * See the Gson User Guide
+3:106c
+ *
See the Gson User Guide
+====3
+1:100c
+2:101c
+ * @see com.google.gson.reflect.TypeToken
+3:109,136c
+ *
Lenient JSON handling
+ * For legacy reasons most of the {@code Gson} methods allow JSON data which does not
+ * comply with the JSON specification, regardless of whether {@link GsonBuilder#setLenient()}
+ * is used or not. If this behavior is not desired, the following workarounds can be used:
+ *
+ * Serialization
+ *
+ * Use {@link #getAdapter(Class)} to obtain the adapter for the type to be serialized
+ * When using an existing {@code JsonWriter}, manually apply the writer settings of this
+ * {@code Gson} instance listed by {@link #newJsonWriter(Writer)}.
+ * Otherwise, when not using an existing {@code JsonWriter}, use {@link #newJsonWriter(Writer)}
+ * to construct one.
+ * Call {@link TypeAdapter#write(JsonWriter, Object)}
+ *
+ *
+ * Deserialization
+ *
+ * Use {@link #getAdapter(Class)} to obtain the adapter for the type to be deserialized
+ * When using an existing {@code JsonReader}, manually apply the reader settings of this
+ * {@code Gson} instance listed by {@link #newJsonReader(Reader)}.
+ * Otherwise, when not using an existing {@code JsonReader}, use {@link #newJsonReader(Reader)}
+ * to construct one.
+ * Call {@link TypeAdapter#read(JsonReader)}
+ * Call {@link JsonReader#peek()} and verify that the result is {@link JsonToken#END_DOCUMENT}
+ * to make sure there is no trailing data
+ *
+ *
+ * @see TypeToken
+====3
+1:120c
+2:121c
+ private static final TypeToken> NULL_KEY_SURROGATE = TypeToken.get(Object.class);
+3:155a
+====1
+1:130,131c
+ private final ThreadLocal, FutureTypeAdapter>>> calls
+ = new ThreadLocal, FutureTypeAdapter>>>();
+2:131,132c
+3:165,166c
+ // Uses LinkedHashMap because iteration order is important, see getAdapter() implementation below
+ private final ThreadLocal, TypeAdapter>>> calls = new ThreadLocal<>();
+====
+1:133c
+ private final Map, TypeAdapter>> typeTokenCache = new ConcurrentHashMap, TypeAdapter>>();
+2:134c
+ private final ConcurrentMap, TypeAdapter>> typeTokenCache = new ConcurrentHashMap, TypeAdapter>>();
+3:168c
+ private final ConcurrentMap, TypeAdapter>> typeTokenCache = new ConcurrentHashMap<>();
+====3
+1:158a
+2:159a
+3:194c
+ final List reflectionFilters;
+====3
+1:185c
+2:186c
+ * The default field naming policy for the output Json is same as in Java. So, a Java class
+3:221c
+ * The default field naming policy for the output JSON is same as in Java. So, a Java class
+====3
+1:187c
+2:188c
+ * Json. The same rules are applied for mapping incoming Json to the Java classes. You can
+3:223c
+ * JSON. The same rules are applied for mapping incoming JSON to the Java classes. You can
+====3
+1:202c
+2:203c
+ Collections.emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY);
+3:238,239c
+ Collections.emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY,
+ Collections.emptyList());
+====3
+1:214c
+2:215c
+ ToNumberStrategy objectToNumberStrategy, ToNumberStrategy numberToNumberStrategy) {
+3:251,252c
+ ToNumberStrategy objectToNumberStrategy, ToNumberStrategy numberToNumberStrategy,
+ List reflectionFilters) {
+====3
+1:218c
+2:219c
+ this.constructorConstructor = new ConstructorConstructor(instanceCreators, useJdkUnsafe);
+3:256c
+ this.constructorConstructor = new ConstructorConstructor(instanceCreators, useJdkUnsafe, reflectionFilters);
+====3
+1:234a
+2:235a
+3:273c
+ this.reflectionFilters = reflectionFilters;
+====3
+1:236c
+2:237c
+ List factories = new ArrayList();
+3:275c
+ List factories = new ArrayList<>();
+====3
+1:299c
+2:300c
+ constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
+3:338c
+ constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory, reflectionFilters));
+====3
+1:308a
+2:309a
+3:348c
+ * @since 2.8.3
+====3
+1:371c
+2:372c
+ out.value(value);
+3:411c
+ out.value(doubleValue);
+====3
+1:395c
+2:396c
+ out.value(value);
+3:435,438c
+ // For backward compatibility don't call `JsonWriter.value(float)` because that method has
+ // been newly added and not all custom JsonWriter implementations might override it yet
+ Number floatNumber = value instanceof Float ? value : floatValue;
+ out.value(floatNumber);
+====3
+1:452c
+2:453c
+ List list = new ArrayList();
+3:495c
+ List list = new ArrayList<>();
+====3
+1:475c
+2:476c
+ @SuppressWarnings("unchecked")
+3:517a
+====3
+1:477c
+2:478c
+ TypeAdapter> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
+3:519,520c
+ Objects.requireNonNull(type, "type must not be null");
+ TypeAdapter> cached = typeTokenCache.get(type);
+====3
+1:479c
+2:480c
+ return (TypeAdapter) cached;
+3:522,524c
+ @SuppressWarnings("unchecked")
+ TypeAdapter adapter = (TypeAdapter) cached;
+ return adapter;
+====1
+1:482,483c
+ Map, FutureTypeAdapter>> threadCalls = calls.get();
+ boolean requiresThreadLocalCleanup = false;
+2:483,484c
+3:527,528c
+ LinkedHashMap, TypeAdapter>> threadCalls = calls.get();
+ boolean isInitialAdapterRequest = false;
+====1
+1:485c
+ threadCalls = new HashMap, FutureTypeAdapter>>();
+2:486c
+3:530c
+ threadCalls = new LinkedHashMap<>();
+====1
+1:487c
+ requiresThreadLocalCleanup = true;
+2:488c
+3:532c
+ isInitialAdapterRequest = true;
+====
+1:491c
+ FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type);
+2:492c
+ TypeAdapter ongoingCall = (TypeAdapter) threadCalls.get(type);
+3:536,537c
+ @SuppressWarnings("unchecked")
+ TypeAdapter ongoingCall = (TypeAdapter) threadCalls.get(type);
+====1
+1:495a
+2:497,498c
+3:542,543c
+ int existingAdaptersCount = threadCalls.size();
+ boolean foundCandidate = false;
+====1
+1:497c
+ FutureTypeAdapter call = new FutureTypeAdapter();
+2:500c
+3:545c
+ FutureTypeAdapter call = new FutureTypeAdapter<>();
+====
+1:504c
+ typeTokenCache.put(type, candidate);
+2:507,519c
+ // Replace future adapter with actual adapter
+ threadCalls.put(type, candidate);
+
+ if (isInitialAdapterRequest) {
+ // Publish resolved adapters to all threads
+ // Can only do this for the initial request because cyclic dependency TypeA -> TypeB -> TypeA
+ // would otherwise publish adapter for TypeB which uses not yet resolved adapter for TypeA
+ // See https://github.com/google/gson/issues/625
+ for (Map.Entry, TypeAdapter>> resolvedAdapterEntry : threadCalls.entrySet()) {
+ typeTokenCache.putIfAbsent(resolvedAdapterEntry.getKey(), resolvedAdapterEntry.getValue());
+ }
+ }
+ foundCandidate = true;
+3:552,570c
+ // Replace future adapter with actual adapter
+ threadCalls.put(type, candidate);
+
+ if (isInitialAdapterRequest) {
+ // Publish resolved adapters to all threads
+ // Can only do this for the initial request because cyclic dependency TypeA -> TypeB -> TypeA
+ // would otherwise publish adapter for TypeB which uses not yet resolved adapter for TypeA
+ // See https://github.com/google/gson/issues/625
+ for (Map.Entry, TypeAdapter>> resolvedAdapterEntry : threadCalls.entrySet()) {
+ typeTokenCache.putIfAbsent(resolvedAdapterEntry.getKey(), resolvedAdapterEntry.getValue());
+ }
+
+ @SuppressWarnings("unchecked")
+ TypeAdapter actualAdapter = (TypeAdapter) typeTokenCache.get(type);
+ // Prefer the actual adapter, in case putIfAbsent call above had no effect because other
+ // thread already concurrently added other adapter instance for the same type
+ candidate = actualAdapter;
+ }
+ foundCandidate = true;
+====1
+1:510,512c
+ threadCalls.remove(type);
+
+ if (requiresThreadLocalCleanup) {
+2:525c
+3:576c
+ if (isInitialAdapterRequest) {
+====
+1:514a
+2:528,545c
+ if (!foundCandidate) {
+ Iterator> adaptersIterator = threadCalls.values().iterator();
+ // Skip existing non-broken adapters
+ for (; existingAdaptersCount > 0; existingAdaptersCount--) {
+ adaptersIterator.next();
+ }
+ // Remove this future adapter and all nested ones because they might
+ // refer to broken adapters
+ while (adaptersIterator.hasNext()) {
+ TypeAdapter> brokenAdapter = adaptersIterator.next();
+ if (brokenAdapter instanceof FutureTypeAdapter) {
+ // Mark adapter as broken so user sees useful exception message in
+ // case TypeAdapterFactory leaks reference to broken adapter
+ ((FutureTypeAdapter) brokenAdapter).markBroken();
+ }
+ adaptersIterator.remove();
+ }
+ }
+3:579,596c
+ if (!foundCandidate) {
+ Iterator> adaptersIterator = threadCalls.values().iterator();
+ // Skip existing non-broken adapters
+ for (; existingAdaptersCount > 0; existingAdaptersCount--) {
+ adaptersIterator.next();
+ }
+ // Remove this future adapter and all nested ones because they might
+ // refer to broken adapters
+ while (adaptersIterator.hasNext()) {
+ TypeAdapter> brokenAdapter = adaptersIterator.next();
+ if (brokenAdapter instanceof FutureTypeAdapter) {
+ // Mark adapter as broken so user sees useful exception message in
+ // case TypeAdapterFactory leaks reference to broken adapter
+ ((FutureTypeAdapter>) brokenAdapter).markBroken();
+ }
+ adaptersIterator.remove();
+ }
+ }
+====3
+1:607c
+2:638c
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+3:689c
+ * of Java. Note that this method works fine if any of the object fields are of generic type,
+====3
+1:611,612c
+2:642,643c
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @return Json representation of {@code src}.
+3:693,694c
+ * @param src the object for which JSON representation is to be created
+ * @return JSON representation of {@code src}.
+====3
+1:613a
+2:644a
+3:696,697c
+ *
+ * @see #toJsonTree(Object, Type)
+====3
+1:636a
+2:667a
+3:721,722c
+ *
+ * @see #toJsonTree(Object)
+====3
+1:645c
+2:676c
+ * This method serializes the specified object into its equivalent Json representation.
+3:731c
+ * This method serializes the specified object into its equivalent JSON representation.
+====3
+1:649c
+2:680c
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+3:735c
+ * of Java. Note that this method works fine if any of the object fields are of generic type,
+====3
+1:654c
+2:685c
+ * @param src the object for which Json representation is to be created setting for Gson
+3:740c
+ * @param src the object for which JSON representation is to be created
+====3
+1:655a
+2:686a
+3:742,744c
+ *
+ * @see #toJson(Object, Appendable)
+ * @see #toJson(Object, Type)
+====3
+1:666c
+2:697c
+ * equivalent Json representation. This method must be used if the specified object is a generic
+3:755c
+ * equivalent JSON representation. This method must be used if the specified object is a generic
+====3
+1:677c
+2:708c
+ * @return Json representation of {@code src}
+3:766,769c
+ * @return JSON representation of {@code src}
+ *
+ * @see #toJson(Object, Type, Appendable)
+ * @see #toJson(Object)
+====3
+1:686c
+2:717c
+ * This method serializes the specified object into its equivalent Json representation.
+3:778,779c
+ * This method serializes the specified object into its equivalent JSON representation and
+ * writes it to the writer.
+====3
+1:690c
+2:721c
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+3:783c
+ * of Java. Note that this method works fine if any of the object fields are of generic type,
+====3
+1:694,695c
+2:725,726c
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @param writer Writer to which the Json representation needs to be written
+3:787,788c
+ * @param src the object for which JSON representation is to be created
+ * @param writer Writer to which the JSON representation needs to be written
+====3
+1:697a
+2:728a
+3:791,793c
+ *
+ * @see #toJson(Object)
+ * @see #toJson(Object, Type, Appendable)
+====3
+1:709,710c
+2:740,741c
+ * equivalent Json representation. This method must be used if the specified object is a generic
+ * type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
+3:805,807c
+ * equivalent JSON representation and writes it to the writer.
+ * This method must be used if the specified object is a generic type. For non-generic objects,
+ * use {@link #toJson(Object, Appendable)} instead.
+====3
+1:719c
+2:750c
+ * @param writer Writer to which the Json representation of src needs to be written.
+3:816c
+ * @param writer Writer to which the JSON representation of src needs to be written.
+====3
+1:721a
+2:752a
+3:819,821c
+ *
+ * @see #toJson(Object, Type)
+ * @see #toJson(Object, Appendable)
+====3
+1:734a
+2:765a
+3:835,843c
+ *
+ * The JSON data is written in {@linkplain JsonWriter#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided writer. The lenient mode setting
+ * of the writer is restored once this method returns.
+ *
+ *
The 'HTML-safe' and 'serialize {@code null}' settings of this {@code Gson} instance
+ * (configured by the {@link GsonBuilder}) are applied, and the original settings of the
+ * writer are restored once this method returns.
+ *
+====3
+1:737c
+2:768c
+ @SuppressWarnings("unchecked")
+3:845a
+====3
+1:739c
+2:770c
+ TypeAdapter> adapter = getAdapter(TypeToken.get(typeOfSrc));
+3:847,848c
+ @SuppressWarnings("unchecked")
+ TypeAdapter adapter = (TypeAdapter) getAdapter(TypeToken.get(typeOfSrc));
+====3
+1:747c
+2:778c
+ ((TypeAdapter) adapter).write(writer, src);
+3:856c
+ adapter.write(writer, src);
+====3
+1:778c
+2:809c
+ * @param writer Writer to which the Json representation needs to be written
+3:887c
+ * @param writer Writer to which the JSON representation needs to be written
+====3
+1:832a
+2:863a
+3:942,950c
+ *
+ * The JSON data is written in {@linkplain JsonWriter#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided writer. The lenient mode setting
+ * of the writer is restored once this method returns.
+ *
+ *
The 'HTML-safe' and 'serialize {@code null}' settings of this {@code Gson} instance
+ * (configured by the {@link GsonBuilder}) are applied, and the original settings of the
+ * writer are restored once this method returns.
+ *
+====3
+1:858c
+2:889c
+ * This method deserializes the specified Json into an object of the specified class. It is not
+3:976c
+ * This method deserializes the specified JSON into an object of the specified class. It is not
+====3
+1:864c
+2:895c
+ * {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
+3:982c
+ * {@link #fromJson(String, TypeToken)}. If you have the JSON in a {@link Reader} instead of
+====3
+1:866a
+2:897a
+3:985,987c
+ *
An exception is thrown if the JSON string has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is not desired.
+ *
+====3
+1:873a
+2:904a
+3:995,997c
+ *
+ * @see #fromJson(Reader, Class)
+ * @see #fromJson(String, TypeToken)
+====3
+1:876c
+2:907c
+ Object object = fromJson(json, (Type) classOfT);
+3:1000c
+ T object = fromJson(json, TypeToken.get(classOfT));
+====3
+1:881c
+2:912c
+ * This method deserializes the specified Json into an object of the specified type. This method
+3:1005c
+ * This method deserializes the specified JSON into an object of the specified type. This method
+====3
+1:883c
+2:914c
+ * {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
+3:1007c
+ * {@link #fromJson(String, Class)} instead. If you have the JSON in a {@link Reader} instead of
+====3
+1:886,889c
+2:917,920c
+ * @param the type of the desired object
+ * @param json the string from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src. You can obtain this type by using the
+ * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
+3:1010,1047c
+ * Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(String, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe.
+ *
+ *
An exception is thrown if the JSON string has multiple top-level JSON elements,
+ * or if there is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is
+ * not desired.
+ *
+ * @param the type of the desired object
+ * @param json the string from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}
+ * or if {@code json} is empty.
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+ *
+ * @see #fromJson(Reader, Type)
+ * @see #fromJson(String, Class)
+ * @see #fromJson(String, TypeToken)
+ */
+ @SuppressWarnings("unchecked")
+ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
+ return (T) fromJson(json, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * This method deserializes the specified JSON into an object of the specified type. This method
+ * is useful if the specified object is a generic type. For non-generic objects, use
+ * {@link #fromJson(String, Class)} instead. If you have the JSON in a {@link Reader} instead of
+ * a String, use {@link #fromJson(Reader, TypeToken)} instead.
+ *
+ * An exception is thrown if the JSON string has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, TypeToken)} if this behavior is not desired.
+ *
+ * @param the type of the desired object
+ * @param json the string from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+====3
+1:892c
+2:923c
+ * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+3:1050c
+ * new TypeToken<Collection<Foo>>(){}
+====3
+1:896,897c
+2:927,928c
+ * @throws JsonParseException if json is not a valid representation for an object of type typeOfT
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+3:1054,1058c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of the type typeOfT
+ *
+ * @see #fromJson(Reader, TypeToken)
+ * @see #fromJson(String, Class)
+ * @since 2.10
+====3
+1:899,900c
+2:930,931c
+ @SuppressWarnings("unchecked")
+ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
+3:1060c
+ public T fromJson(String json, TypeToken typeOfT) throws JsonSyntaxException {
+====3
+1:905,906c
+2:936,937c
+ T target = (T) fromJson(reader, typeOfT);
+ return target;
+3:1065c
+ return fromJson(reader, typeOfT);
+====3
+1:910c
+2:941c
+ * This method deserializes the Json read from the specified reader into an object of the
+3:1069c
+ * This method deserializes the JSON read from the specified reader into an object of the
+====3
+1:914c
+2:945c
+ * this method works fine if the any of the fields of the specified object are generics, just the
+3:1073c
+ * this method works fine if any of the fields of the specified object are generics, just the
+====3
+1:916c
+2:947c
+ * invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
+3:1075c
+ * invoke {@link #fromJson(Reader, TypeToken)}. If you have the JSON in a String form instead of a
+====3
+1:918a
+2:949a
+3:1078,1080c
+ * An exception is thrown if the JSON data has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is not desired.
+ *
+====3
+1:920c
+2:951c
+ * @param json the reader producing the Json from which the object is to be deserialized.
+3:1082c
+ * @param json the reader producing the JSON from which the object is to be deserialized.
+====3
+1:922c
+2:953c
+ * @return an object of type T from the string. Returns {@code null} if {@code json} is at EOF.
+3:1084c
+ * @return an object of type T from the Reader. Returns {@code null} if {@code json} is at EOF.
+====3
+1:924c
+2:955c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+3:1086c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+====3
+1:925a
+2:956a
+3:1088,1090c
+ *
+ * @see #fromJson(String, Class)
+ * @see #fromJson(Reader, TypeToken)
+====3
+1:928,930c
+2:959,961c
+ JsonReader jsonReader = newJsonReader(json);
+ Object object = fromJson(jsonReader, classOfT);
+ assertFullConsumption(object, jsonReader);
+3:1093c
+ T object = fromJson(json, TypeToken.get(classOfT));
+====3
+1:935c
+2:966c
+ * This method deserializes the Json read from the specified reader into an object of the
+3:1098c
+ * This method deserializes the JSON read from the specified reader into an object of the
+====3
+1:937c
+2:968c
+ * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
+3:1100c
+ * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the JSON in a
+====3
+1:939a
+2:970a
+3:1103,1110c
+ *
Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(Reader, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe.
+ *
+ *
An exception is thrown if the JSON data has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is not desired.
+ *
+====3
+1:941,948c
+2:972,979c
+ * @param json the reader producing Json from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src. You can obtain this type by using the
+ * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is at EOF.
+3:1112,1114c
+ * @param json the reader producing JSON from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the Reader. Returns {@code null} if {@code json} is at EOF.
+====3
+1:950c
+2:981c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+3:1116c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+====3
+1:951a
+2:982a
+3:1118,1121c
+ *
+ * @see #fromJson(String, Type)
+ * @see #fromJson(Reader, Class)
+ * @see #fromJson(Reader, TypeToken)
+====3
+1:954a
+2:985a
+3:1125,1153c
+ return (T) fromJson(json, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * This method deserializes the JSON read from the specified reader into an object of the
+ * specified type. This method is useful if the specified object is a generic type. For
+ * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the JSON in a
+ * String form instead of a {@link Reader}, use {@link #fromJson(String, TypeToken)} instead.
+ *
+ * An exception is thrown if the JSON data has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, TypeToken)} if this behavior is not desired.
+ *
+ * @param the type of the desired object
+ * @param json the reader producing JSON from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * new TypeToken<Collection<Foo>>(){}
+ *
+ * @return an object of type T from the Reader. Returns {@code null} if {@code json} is at EOF.
+ * @throws JsonIOException if there was a problem reading from the Reader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type of typeOfT
+ *
+ * @see #fromJson(String, TypeToken)
+ * @see #fromJson(Reader, Class)
+ * @since 2.10
+ */
+ public T fromJson(Reader json, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException {
+====3
+1:956c
+2:987c
+ T object = (T) fromJson(jsonReader, typeOfT);
+3:1155c
+ T object = fromJson(jsonReader, typeOfT);
+====3
+1:964c
+2:995c
+ throw new JsonIOException("JSON document was not fully consumed.");
+3:1163c
+ throw new JsonSyntaxException("JSON document was not fully consumed.");
+====3
+1:972a
+2:1003a
+3:1172,1174c
+ // fromJson(JsonReader, Class) is unfortunately missing and cannot be added now without breaking
+ // source compatibility in certain cases, see https://github.com/google/gson/pull/1700#discussion_r973764414
+
+====3
+1:974c
+2:1005c
+ * Reads the next JSON value from {@code reader} and convert it to an object
+3:1176c
+ * Reads the next JSON value from {@code reader} and converts it to an object
+====3
+1:976c
+2:1007c
+ * Since Type is not parameterized by T, this method is type unsafe and should be used carefully
+3:1177a
+====3
+1:978,979c
+2:1009,1010c
+ * @throws JsonIOException if there was a problem writing to the Reader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+3:1179,1200c
+ * Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(JsonReader, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe. If the provided type is a
+ * {@code Class} the {@code TypeToken} can be created with {@link TypeToken#get(Class)}.
+ *
+ *
Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
+ * multiple top-level JSON elements, or if there is trailing data.
+ *
+ *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided reader. The lenient mode setting
+ * of the reader is restored once this method returns.
+ *
+ * @param the type of the desired object
+ * @param reader the reader whose next JSON value should be deserialized
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the JsonReader. Returns {@code null} if {@code reader} is at EOF.
+ * @throws JsonIOException if there was a problem reading from the JsonReader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+ *
+ * @see #fromJson(Reader, Type)
+ * @see #fromJson(JsonReader, TypeToken)
+====3
+1:982a
+2:1013a
+3:1204,1237c
+ return (T) fromJson(reader, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * Reads the next JSON value from {@code reader} and converts it to an object
+ * of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF.
+ * This method is useful if the specified object is a generic type. For non-generic objects,
+ * {@link #fromJson(JsonReader, Type)} can be called, or {@link TypeToken#get(Class)} can
+ * be used to create the type token.
+ *
+ * Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
+ * multiple top-level JSON elements, or if there is trailing data.
+ *
+ *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided reader. The lenient mode setting
+ * of the reader is restored once this method returns.
+ *
+ * @param the type of the desired object
+ * @param reader the reader whose next JSON value should be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * new TypeToken<Collection<Foo>>(){}
+ *
+ * @return an object of type T from the JsonReader. Returns {@code null} if {@code reader} is at EOF.
+ * @throws JsonIOException if there was a problem reading from the JsonReader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of the type typeOfT
+ *
+ * @see #fromJson(Reader, TypeToken)
+ * @see #fromJson(JsonReader, Type)
+ * @since 2.10
+ */
+ public T fromJson(JsonReader reader, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException {
+====3
+1:989,990c
+2:1020,1021c
+ TypeToken typeToken = (TypeToken) TypeToken.get(typeOfT);
+ TypeAdapter typeAdapter = getAdapter(typeToken);
+3:1244c
+ TypeAdapter typeAdapter = getAdapter(typeOfT);
+====3
+1:1017c
+2:1048c
+ * This method deserializes the Json read from the specified parse tree into an object of the
+3:1271c
+ * This method deserializes the JSON read from the specified parse tree into an object of the
+====3
+1:1021c
+2:1052c
+ * this method works fine if the any of the fields of the specified object are generics, just the
+3:1275c
+ * this method works fine if any of the fields of the specified object are generics, just the
+====3
+1:1023c
+2:1054c
+ * invoke {@link #fromJson(JsonElement, Type)}.
+3:1277,1278c
+ * invoke {@link #fromJson(JsonElement, TypeToken)}.
+ *
+====3
+1:1028c
+2:1059c
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}
+3:1283c
+ * @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
+====3
+1:1030c
+2:1061c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+3:1285c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type classOfT
+====3
+1:1031a
+2:1062a
+3:1287,1289c
+ *
+ * @see #fromJson(Reader, Class)
+ * @see #fromJson(JsonElement, TypeToken)
+====3
+1:1034c
+2:1065c
+ Object object = fromJson(json, (Type) classOfT);
+3:1292c
+ T object = fromJson(json, TypeToken.get(classOfT));
+====3
+1:1039c
+2:1070c
+ * This method deserializes the Json read from the specified parse tree into an object of the
+3:1297c
+ * This method deserializes the JSON read from the specified parse tree into an object of the
+====3
+1:1042a
+2:1073a
+3:1301,1305c
+ * Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(JsonElement, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe.
+ *
+====3
+1:1046,1052c
+2:1077,1083c
+ * @param typeOfT The specific genericized type of src. You can obtain this type by using the
+ * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}
+3:1309,1310c
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
+====3
+1:1055a
+2:1086a
+3:1314,1317c
+ *
+ * @see #fromJson(Reader, Type)
+ * @see #fromJson(JsonElement, Class)
+ * @see #fromJson(JsonElement, TypeToken)
+====3
+1:1058a
+2:1089a
+3:1321,1346c
+ return (T) fromJson(json, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * This method deserializes the JSON read from the specified parse tree into an object of the
+ * specified type. This method is useful if the specified object is a generic type. For
+ * non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
+ *
+ * @param the type of the desired object
+ * @param json the root of the parse tree of {@link JsonElement}s from which the object is to
+ * be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * new TypeToken<Collection<Foo>>(){}
+ *
+ * @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
+ * or if {@code json} is empty.
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+ *
+ * @see #fromJson(Reader, TypeToken)
+ * @see #fromJson(JsonElement, Class)
+ * @since 2.10
+ */
+ public T fromJson(JsonElement json, TypeToken typeOfT) throws JsonSyntaxException {
+====3
+1:1062c
+2:1093c
+ return (T) fromJson(new JsonTreeReader(json), typeOfT);
+3:1350c
+ return fromJson(new JsonTreeReader(json), typeOfT);
+====
+1:1065,1066c
+ static class FutureTypeAdapter extends TypeAdapter {
+ private TypeAdapter delegate;
+2:1096,1098c
+ static class FutureTypeAdapter extends TypeAdapter {
+ private TypeAdapter delegate = null;
+ private boolean isBroken = false;
+3:1353,1355c
+ static class FutureTypeAdapter extends SerializationDelegatingTypeAdapter {
+ private TypeAdapter delegate = null;
+ private boolean isBroken = false;
+====
+1:1075c
+ @Override public T read(JsonReader in) throws IOException {
+2:1107,1115c
+ public void markBroken() {
+ isBroken = true;
+ }
+
+ private TypeAdapter getResolvedDelegate() {
+ TypeAdapter delegate = this.delegate;
+ if (isBroken) {
+ throw new IllegalStateException("Broken adapter has been leaked by TypeAdapterFactory");
+ }
+3:1364,1372c
+ public void markBroken() {
+ isBroken = true;
+ }
+
+ private TypeAdapter delegate() {
+ TypeAdapter delegate = this.delegate;
+ if (isBroken) {
+ throw new IllegalStateException("Broken adapter has been leaked by TypeAdapterFactory");
+ }
+====1
+1:1077c
+ throw new IllegalStateException();
+2:1117,1120c
+3:1374,1377c
+ // Can occur when adapter is leaked to other thread or when adapter is used for (de-)serialization
+ // directly within the TypeAdapterFactory which requested it
+ throw new IllegalStateException("Adapter for type with cyclic dependency has been used"
+ + " before dependency has been resolved");
+====
+1:1079c
+ return delegate.read(in);
+2:1122,1126c
+ return delegate;
+ }
+
+ @Override public T read(JsonReader in) throws IOException {
+ return getResolvedDelegate().read(in);
+3:1379,1387c
+ return delegate;
+ }
+
+ @Override public TypeAdapter getSerializationDelegate() {
+ return delegate();
+ }
+
+ @Override public T read(JsonReader in) throws IOException {
+ return delegate().read(in);
+====
+1:1083,1086c
+ if (delegate == null) {
+ throw new IllegalStateException();
+ }
+ delegate.write(out, value);
+2:1130c
+ getResolvedDelegate().write(out, value);
+3:1391c
+ delegate().write(out, value);
diff --git a/src/python/merge_conflict_analysis_diffs/1006/git_hires_merge/diff_GsonTest.java.txt b/src/python/merge_conflict_analysis_diffs/1006/git_hires_merge/diff_GsonTest.java.txt
new file mode 100644
index 0000000000..76854475ca
--- /dev/null
+++ b/src/python/merge_conflict_analysis_diffs/1006/git_hires_merge/diff_GsonTest.java.txt
@@ -0,0 +1,681 @@
+====1
+1:18a
+2:19c
+3:19c
+ import com.google.gson.Gson.FutureTypeAdapter;
+====1
+1:19a
+2:21c
+3:21c
+ import com.google.gson.reflect.TypeToken;
+====3
+1:29a
+2:31a
+3:32c
+ import java.util.Collections;
+====
+1:30a
+2:33,34c
+ import java.util.concurrent.CountDownLatch;
+ import java.util.concurrent.atomic.AtomicReference;
+3:34,36c
+ import java.util.concurrent.CountDownLatch;
+ import java.util.concurrent.atomic.AtomicInteger;
+ import java.util.concurrent.atomic.AtomicReference;
+====3
+1:59c
+2:63c
+ CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY);
+3:65,66c
+ CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY,
+ Collections.emptyList());
+====3
+1:73c
+2:77c
+ CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY);
+3:80,81c
+ CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY,
+ Collections.emptyList());
+====3
+1:88a
+2:92a
+3:97,149c
+ public void testGetAdapter_Null() {
+ Gson gson = new Gson();
+ try {
+ gson.getAdapter((TypeToken>) null);
+ fail();
+ } catch (NullPointerException e) {
+ assertEquals("type must not be null", e.getMessage());
+ }
+ }
+
+ public void testGetAdapter_Concurrency() {
+ final AtomicInteger adapterInstancesCreated = new AtomicInteger(0);
+ final AtomicReference> threadAdapter = new AtomicReference<>();
+ final Class> requestedType = Number.class;
+
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new TypeAdapterFactory() {
+ private volatile boolean isFirstCall = true;
+
+ @Override public TypeAdapter create(final Gson gson, TypeToken type) {
+ if (isFirstCall) {
+ isFirstCall = false;
+
+ // Create a separate thread which requests an adapter for the same type
+ // This will cause this factory to return a different adapter instance than
+ // the one it is currently creating
+ Thread thread = new Thread() {
+ @Override public void run() {
+ threadAdapter.set(gson.getAdapter(requestedType));
+ }
+ };
+ thread.start();
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Create a new dummy adapter instance
+ adapterInstancesCreated.incrementAndGet();
+ return new DummyAdapter<>();
+ }
+ })
+ .create();
+
+ TypeAdapter> adapter = gson.getAdapter(requestedType);
+ assertTrue(adapter instanceof DummyAdapter);
+ assertEquals(2, adapterInstancesCreated.get());
+ // Should be the same adapter instance the concurrent thread received
+ assertSame(threadAdapter.get(), adapter);
+ }
+
+====
+1:154a
+2:159,374c
+
+ /**
+ * Verifies that {@link Gson#getAdapter(TypeToken)} does not put broken adapters
+ * into {@code typeTokenCache} when caller of nested {@code getAdapter} discards
+ * exception, e.g.:
+ *
+ * Field dependencies:
+ * ClassA
+ * -> ClassB1
+ * -> ClassC -> ClassB1
+ * -> ClassX
+ * | ClassB2
+ *
+ * Let's assume the factory for ClassX throws an exception.
+ * 1. Factory for ClassA finds field of type ClassB1
+ * 2. Factory for ClassB1 finds field of type ClassC
+ * 3. Factory for ClassC find fields of type ClassB1 => stores future adapter
+ * 4. Factory for ClassB1 finds field of type ClassX => ClassX factory throws exception
+ * 5. Factory for ClassA ignores exception from getAdapter(ClassB1) and tries as alternative getting
+ * adapter for ClassB2
+ *
+ * Then Gson must not cache adapter for ClassC because it refers to broken adapter
+ * for ClassB1 (since ClassX threw exception).
+ */
+ public void testGetAdapterDiscardedException() throws Exception {
+ final TypeAdapter> alternativeAdapter = new DummyAdapter<>();
+ final AtomicReference> leakedAdapter = new AtomicReference<>();
+
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new TypeAdapterFactory() {
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (type.getRawType() == CustomClassA.class) {
+ // Factory will throw for CustomClassB1; discard exception
+ try {
+ gson.getAdapter(CustomClassB1.class);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertEquals("test exception", e.getMessage());
+ }
+
+ @SuppressWarnings("unchecked")
+ TypeAdapter adapter = (TypeAdapter) alternativeAdapter;
+ return adapter;
+ }
+ else if (type.getRawType() == CustomClassB1.class) {
+ gson.getAdapter(CustomClassC.class);
+ // Will throw exception
+ gson.getAdapter(CustomClassX.class);
+
+ throw new AssertionError("Factory should have thrown exception for CustomClassX");
+ }
+ else if (type.getRawType() == CustomClassC.class) {
+ // Will return future adapter due to cyclic dependency B1 -> C -> B1
+ TypeAdapter> adapter = gson.getAdapter(CustomClassB1.class);
+ assertTrue(adapter instanceof FutureTypeAdapter);
+ // Pretend this factory somehow leaks this FutureTypeAdapter
+ leakedAdapter.set(adapter);
+ return new DummyAdapter();
+ }
+ else if (type.getRawType() == CustomClassX.class) {
+ // Always throw exception
+ throw new RuntimeException("test exception");
+ }
+
+ throw new AssertionError("Requested adapter for unexpected type: " + type);
+ }
+ })
+ .create();
+
+ assertSame(alternativeAdapter, gson.getAdapter(CustomClassA.class));
+ // Gson must not have cached broken adapters for CustomClassB1 and CustomClassC
+ try {
+ gson.getAdapter(CustomClassB1.class);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertEquals("test exception", e.getMessage());
+ }
+ try {
+ gson.getAdapter(CustomClassC.class);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertEquals("test exception", e.getMessage());
+ }
+
+ // Leaked adapter should have been marked as "broken"
+ try {
+ leakedAdapter.get().fromJson("{}");
+ fail("Expected exception");
+ } catch (IllegalStateException e) {
+ assertEquals("Broken adapter has been leaked by TypeAdapterFactory", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that two threads calling {@link Gson#getAdapter(TypeToken)} do not see the
+ * same unresolved {@link FutureTypeAdapter} instance, since that would not be thread-safe.
+ *
+ * This test constructs the cyclic dependency CustomClassA -> CustomClassB1 -> CustomClassA
+ * and lets one thread wait after the adapter for CustomClassB1 has been obtained (which still
+ * contains the nested unresolved FutureTypeAdapter for CustomClassA).
+ */
+ public void testGetAdapterFutureAdapterConcurrency() throws Exception {
+ /**
+ * Adapter which wraps another adapter. Can be imagined as a simplified version of the
+ * ReflectiveTypeAdapterFactory$Adapter.
+ */
+ class WrappingAdapter extends TypeAdapter {
+ final TypeAdapter> wrapped;
+ int callCount = 0;
+
+ WrappingAdapter(TypeAdapter> wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override public void write(JsonWriter out, T value) throws IOException {
+ // Due to how this test is set up there is infinite recursion, therefore
+ // need to track how deeply nested this call is
+ if (callCount == 0) {
+ callCount++;
+ out.beginArray();
+ wrapped.write(out, null);
+ out.endArray();
+ } else {
+ out.value("wrapped-nested");
+ }
+ }
+
+ @Override public T read(JsonReader in) throws IOException {
+ throw new AssertionError("not needed for this test");
+ }
+ }
+
+ final CountDownLatch isThreadWaiting = new CountDownLatch(1);
+ final CountDownLatch canThreadProceed = new CountDownLatch(1);
+
+ final Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new TypeAdapterFactory() {
+ // volatile instead of AtomicBoolean is safe here because CountDownLatch prevents
+ // "true" concurrency
+ volatile boolean isFirstCaller = true;
+
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ Class> raw = type.getRawType();
+
+ if (raw == CustomClassA.class) {
+ // Retrieves a WrappingAdapter containing a nested FutureAdapter for CustomClassA
+ TypeAdapter> adapter = gson.getAdapter(CustomClassB1.class);
+
+ // Let thread wait so the FutureAdapter for CustomClassA nested in the adapter
+ // for CustomClassB1 has not been resolved yet
+ if (isFirstCaller) {
+ isFirstCaller = false;
+ isThreadWaiting.countDown();
+
+ try {
+ canThreadProceed.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return new WrappingAdapter<>(adapter);
+ }
+ else if (raw == CustomClassB1.class) {
+ TypeAdapter> adapter = gson.getAdapter(CustomClassA.class);
+ assertTrue(adapter instanceof FutureTypeAdapter);
+ return new WrappingAdapter<>(adapter);
+ }
+ else {
+ throw new AssertionError("Adapter for unexpected type requested: " + raw);
+ }
+ }
+ })
+ .create();
+
+ final AtomicReference> otherThreadAdapter = new AtomicReference<>();
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ otherThreadAdapter.set(gson.getAdapter(CustomClassA.class));
+ }
+ };
+ thread.start();
+
+ // Wait until other thread has obtained FutureAdapter
+ isThreadWaiting.await();
+ TypeAdapter> adapter = gson.getAdapter(CustomClassA.class);
+ // Should not fail due to referring to unresolved FutureTypeAdapter
+ assertEquals("[[\"wrapped-nested\"]]", adapter.toJson(null));
+
+ // Let other thread proceed and have it resolve its FutureTypeAdapter
+ canThreadProceed.countDown();
+ thread.join();
+ assertEquals("[[\"wrapped-nested\"]]", otherThreadAdapter.get().toJson(null));
+ }
+
+ private static class DummyAdapter extends TypeAdapter {
+ @Override public void write(JsonWriter out, T value) throws IOException {
+ throw new AssertionError("not needed for this test");
+ }
+
+ @Override public T read(JsonReader in) throws IOException {
+ throw new AssertionError("not needed for this test");
+ }
+ }
+
+ private static class CustomClassA {
+ }
+ private static class CustomClassB1 {
+ }
+ private static class CustomClassC {
+ }
+ private static class CustomClassX {
+ }
+3:216,581c
+
+ /**
+ * Modifying a GsonBuilder obtained from {@link Gson#newBuilder()} of a
+ * {@code new Gson()} should not affect the Gson instance it came from.
+ */
+ public void testDefaultGsonNewBuilderModification() {
+ Gson gson = new Gson();
+ GsonBuilder gsonBuilder = gson.newBuilder();
+
+ // Modifications of `gsonBuilder` should not affect `gson` object
+ gsonBuilder.registerTypeAdapter(CustomClass1.class, new TypeAdapter() {
+ @Override public CustomClass1 read(JsonReader in) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void write(JsonWriter out, CustomClass1 value) throws IOException {
+ out.value("custom-adapter");
+ }
+ });
+ gsonBuilder.registerTypeHierarchyAdapter(CustomClass2.class, new JsonSerializer() {
+ @Override public JsonElement serialize(CustomClass2 src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive("custom-hierarchy-adapter");
+ }
+ });
+ gsonBuilder.registerTypeAdapter(CustomClass3.class, new InstanceCreator() {
+ @Override public CustomClass3 createInstance(Type type) {
+ return new CustomClass3("custom-instance");
+ }
+ });
+
+ assertDefaultGson(gson);
+ // New GsonBuilder created from `gson` should not have been affected by changes either
+ assertDefaultGson(gson.newBuilder().create());
+
+ // But new Gson instance from `gsonBuilder` should use custom adapters
+ assertCustomGson(gsonBuilder.create());
+ }
+
+ private static void assertDefaultGson(Gson gson) {
+ // Should use default reflective adapter
+ String json1 = gson.toJson(new CustomClass1());
+ assertEquals("{}", json1);
+
+ // Should use default reflective adapter
+ String json2 = gson.toJson(new CustomClass2());
+ assertEquals("{}", json2);
+
+ // Should use default instance creator
+ CustomClass3 customClass3 = gson.fromJson("{}", CustomClass3.class);
+ assertEquals(CustomClass3.NO_ARG_CONSTRUCTOR_VALUE, customClass3.s);
+ }
+
+ /**
+ * Modifying a GsonBuilder obtained from {@link Gson#newBuilder()} of a custom
+ * Gson instance (created using a GsonBuilder) should not affect the Gson instance
+ * it came from.
+ */
+ public void testNewBuilderModification() {
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapter(CustomClass1.class, new TypeAdapter() {
+ @Override public CustomClass1 read(JsonReader in) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void write(JsonWriter out, CustomClass1 value) throws IOException {
+ out.value("custom-adapter");
+ }
+ })
+ .registerTypeHierarchyAdapter(CustomClass2.class, new JsonSerializer() {
+ @Override public JsonElement serialize(CustomClass2 src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive("custom-hierarchy-adapter");
+ }
+ })
+ .registerTypeAdapter(CustomClass3.class, new InstanceCreator() {
+ @Override public CustomClass3 createInstance(Type type) {
+ return new CustomClass3("custom-instance");
+ }
+ })
+ .create();
+
+ assertCustomGson(gson);
+
+ // Modify `gson.newBuilder()`
+ GsonBuilder gsonBuilder = gson.newBuilder();
+ gsonBuilder.registerTypeAdapter(CustomClass1.class, new TypeAdapter() {
+ @Override public CustomClass1 read(JsonReader in) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public void write(JsonWriter out, CustomClass1 value) throws IOException {
+ out.value("overwritten custom-adapter");
+ }
+ });
+ gsonBuilder.registerTypeHierarchyAdapter(CustomClass2.class, new JsonSerializer() {
+ @Override public JsonElement serialize(CustomClass2 src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive("overwritten custom-hierarchy-adapter");
+ }
+ });
+ gsonBuilder.registerTypeAdapter(CustomClass3.class, new InstanceCreator() {
+ @Override public CustomClass3 createInstance(Type type) {
+ return new CustomClass3("overwritten custom-instance");
+ }
+ });
+
+ // `gson` object should not have been affected by changes to new GsonBuilder
+ assertCustomGson(gson);
+ // New GsonBuilder based on `gson` should not have been affected either
+ assertCustomGson(gson.newBuilder().create());
+
+ // But new Gson instance from `gsonBuilder` should be affected by changes
+ Gson otherGson = gsonBuilder.create();
+ String json1 = otherGson.toJson(new CustomClass1());
+ assertEquals("\"overwritten custom-adapter\"", json1);
+
+ String json2 = otherGson.toJson(new CustomClass2());
+ assertEquals("\"overwritten custom-hierarchy-adapter\"", json2);
+
+ CustomClass3 customClass3 = otherGson.fromJson("{}", CustomClass3.class);
+ assertEquals("overwritten custom-instance", customClass3.s);
+ }
+
+ private static void assertCustomGson(Gson gson) {
+ String json1 = gson.toJson(new CustomClass1());
+ assertEquals("\"custom-adapter\"", json1);
+
+ String json2 = gson.toJson(new CustomClass2());
+ assertEquals("\"custom-hierarchy-adapter\"", json2);
+
+ CustomClass3 customClass3 = gson.fromJson("{}", CustomClass3.class);
+ assertEquals("custom-instance", customClass3.s);
+ }
+
+ static class CustomClass1 { }
+ static class CustomClass2 { }
+ static class CustomClass3 {
+ static final String NO_ARG_CONSTRUCTOR_VALUE = "default instance";
+
+ final String s;
+
+ public CustomClass3(String s) {
+ this.s = s;
+ }
+
+ public CustomClass3() {
+ this(NO_ARG_CONSTRUCTOR_VALUE);
+ }
+ }
+
+ /**
+ * Verifies that {@link Gson#getAdapter(TypeToken)} does not put broken adapters
+ * into {@code typeTokenCache} when caller of nested {@code getAdapter} discards
+ * exception, e.g.:
+ *
+ * Field dependencies:
+ * ClassA
+ * -> ClassB1
+ * -> ClassC -> ClassB1
+ * -> ClassX
+ * | ClassB2
+ *
+ * Let's assume the factory for ClassX throws an exception.
+ * 1. Factory for ClassA finds field of type ClassB1
+ * 2. Factory for ClassB1 finds field of type ClassC
+ * 3. Factory for ClassC find fields of type ClassB1 => stores future adapter
+ * 4. Factory for ClassB1 finds field of type ClassX => ClassX factory throws exception
+ * 5. Factory for ClassA ignores exception from getAdapter(ClassB1) and tries as alternative getting
+ * adapter for ClassB2
+ *
+ * Then Gson must not cache adapter for ClassC because it refers to broken adapter
+ * for ClassB1 (since ClassX threw exception).
+ */
+ public void testGetAdapterDiscardedException() throws Exception {
+ final TypeAdapter> alternativeAdapter = new DummyAdapter<>();
+ final AtomicReference> leakedAdapter = new AtomicReference<>();
+
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new TypeAdapterFactory() {
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (type.getRawType() == CustomClassA.class) {
+ // Factory will throw for CustomClassB1; discard exception
+ try {
+ gson.getAdapter(CustomClassB1.class);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertEquals("test exception", e.getMessage());
+ }
+
+ @SuppressWarnings("unchecked")
+ TypeAdapter adapter = (TypeAdapter) alternativeAdapter;
+ return adapter;
+ }
+ else if (type.getRawType() == CustomClassB1.class) {
+ gson.getAdapter(CustomClassC.class);
+ // Will throw exception
+ gson.getAdapter(CustomClassX.class);
+
+ throw new AssertionError("Factory should have thrown exception for CustomClassX");
+ }
+ else if (type.getRawType() == CustomClassC.class) {
+ // Will return future adapter due to cyclic dependency B1 -> C -> B1
+ TypeAdapter> adapter = gson.getAdapter(CustomClassB1.class);
+ assertTrue(adapter instanceof FutureTypeAdapter);
+ // Pretend this factory somehow leaks this FutureTypeAdapter
+ leakedAdapter.set(adapter);
+ return new DummyAdapter();
+ }
+ else if (type.getRawType() == CustomClassX.class) {
+ // Always throw exception
+ throw new RuntimeException("test exception");
+ }
+
+ throw new AssertionError("Requested adapter for unexpected type: " + type);
+ }
+ })
+ .create();
+
+ assertSame(alternativeAdapter, gson.getAdapter(CustomClassA.class));
+ // Gson must not have cached broken adapters for CustomClassB1 and CustomClassC
+ try {
+ gson.getAdapter(CustomClassB1.class);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertEquals("test exception", e.getMessage());
+ }
+ try {
+ gson.getAdapter(CustomClassC.class);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertEquals("test exception", e.getMessage());
+ }
+
+ // Leaked adapter should have been marked as "broken"
+ try {
+ leakedAdapter.get().fromJson("{}");
+ fail("Expected exception");
+ } catch (IllegalStateException e) {
+ assertEquals("Broken adapter has been leaked by TypeAdapterFactory", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that two threads calling {@link Gson#getAdapter(TypeToken)} do not see the
+ * same unresolved {@link FutureTypeAdapter} instance, since that would not be thread-safe.
+ *
+ * This test constructs the cyclic dependency CustomClassA -> CustomClassB1 -> CustomClassA
+ * and lets one thread wait after the adapter for CustomClassB1 has been obtained (which still
+ * contains the nested unresolved FutureTypeAdapter for CustomClassA).
+ */
+ public void testGetAdapterFutureAdapterConcurrency() throws Exception {
+ /**
+ * Adapter which wraps another adapter. Can be imagined as a simplified version of the
+ * ReflectiveTypeAdapterFactory$Adapter.
+ */
+ class WrappingAdapter extends TypeAdapter {
+ final TypeAdapter> wrapped;
+ int callCount = 0;
+
+ WrappingAdapter(TypeAdapter> wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override public void write(JsonWriter out, T value) throws IOException {
+ // Due to how this test is set up there is infinite recursion, therefore
+ // need to track how deeply nested this call is
+ try {
+ if (callCount++ == 0) {
+ out.beginArray();
+ wrapped.write(out, null);
+ out.endArray();
+ } else {
+ out.value("wrapped-nested");
+ }
+ } finally {
+ callCount--;
+ }
+ }
+
+ @Override public T read(JsonReader in) throws IOException {
+ throw new AssertionError("not needed for this test");
+ }
+ }
+
+ final CountDownLatch isThreadWaiting = new CountDownLatch(1);
+ final CountDownLatch canThreadProceed = new CountDownLatch(1);
+
+ final Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new TypeAdapterFactory() {
+ // volatile instead of AtomicBoolean is safe here because CountDownLatch prevents
+ // "true" concurrency
+ volatile boolean isFirstCaller = true;
+
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ Class> raw = type.getRawType();
+
+ if (raw == CustomClassA.class) {
+ // Retrieves a WrappingAdapter containing a nested FutureAdapter for CustomClassA
+ TypeAdapter> adapter = gson.getAdapter(CustomClassB1.class);
+
+ // Let thread wait so the FutureAdapter for CustomClassA nested in the adapter
+ // for CustomClassB1 has not been resolved yet
+ if (isFirstCaller) {
+ isFirstCaller = false;
+ isThreadWaiting.countDown();
+
+ try {
+ canThreadProceed.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return new WrappingAdapter<>(adapter);
+ }
+ else if (raw == CustomClassB1.class) {
+ TypeAdapter> adapter = gson.getAdapter(CustomClassA.class);
+ assertTrue(adapter instanceof FutureTypeAdapter);
+ return new WrappingAdapter<>(adapter);
+ }
+ else {
+ throw new AssertionError("Adapter for unexpected type requested: " + raw);
+ }
+ }
+ })
+ .create();
+
+ final AtomicReference> otherThreadAdapter = new AtomicReference<>();
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ otherThreadAdapter.set(gson.getAdapter(CustomClassA.class));
+ }
+ };
+ thread.start();
+
+ // Wait until other thread has obtained FutureAdapter
+ isThreadWaiting.await();
+ TypeAdapter> adapter = gson.getAdapter(CustomClassA.class);
+ // Should not fail due to referring to unresolved FutureTypeAdapter
+ assertEquals("[[\"wrapped-nested\"]]", adapter.toJson(null));
+
+ // Let other thread proceed and have it resolve its FutureTypeAdapter
+ canThreadProceed.countDown();
+ thread.join();
+ assertEquals("[[\"wrapped-nested\"]]", otherThreadAdapter.get().toJson(null));
+ }
+
+ private static class DummyAdapter extends TypeAdapter {
+ @Override public void write(JsonWriter out, T value) throws IOException {
+ throw new AssertionError("not needed for this test");
+ }
+
+ @Override public T read(JsonReader in) throws IOException {
+ throw new AssertionError("not needed for this test");
+ }
+ }
+
+ private static class CustomClassA {
+ }
+ private static class CustomClassB1 {
+ }
+ private static class CustomClassC {
+ }
+ private static class CustomClassX {
+ }
diff --git a/src/python/merge_conflict_analysis_diffs/1006/gitmerge_ort/diff_Gson.java.txt b/src/python/merge_conflict_analysis_diffs/1006/gitmerge_ort/diff_Gson.java.txt
new file mode 100644
index 0000000000..588a5039ad
--- /dev/null
+++ b/src/python/merge_conflict_analysis_diffs/1006/gitmerge_ort/diff_Gson.java.txt
@@ -0,0 +1,1218 @@
+====1
+1:19,37c
+ import java.io.EOFException;
+ import java.io.IOException;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.lang.reflect.Type;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.text.DateFormat;
+ import java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicLongArray;
+
+2:18a
+3:18a
+====1
+1:53a
+2:35c
+3:35c
+ import com.google.gson.internal.bind.SerializationDelegatingTypeAdapter;
+====
+1:60a
+2:43,70c
+ import java.io.EOFException;
+ import java.io.IOException;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.lang.reflect.Type;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.text.DateFormat;
+ import java.util.ArrayList;
+ import java.util.Collections;
+ <<<<<<< HEAD
+ import java.util.Iterator;
+ import java.util.LinkedHashMap;
+ import java.util.List;
+ import java.util.Map;
+ ||||||| 47dea2ee
+ =======
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Objects;
+ >>>>>>> TEMP_RIGHT_BRANCH
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
+ import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicLongArray;
+3:43,63c
+ import java.io.EOFException;
+ import java.io.IOException;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.lang.reflect.Type;
+ import java.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.text.DateFormat;
+ import java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.Iterator;
+ import java.util.LinkedHashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Objects;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
+ import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicLongArray;
+====1
+1:78c
+ * String json = gson.toJson(target); // serializes target to Json
+2:88c
+3:81c
+ * String json = gson.toJson(target); // serializes target to JSON
+====1
+1:82,86c
+ * If the object that your are serializing/deserializing is a {@code ParameterizedType}
+ * (i.e. contains at least one type parameter and may be an array) then you must use the
+ * {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an
+ * example for serializing and deserializing a {@code ParameterizedType}:
+ *
+2:92,98c
+3:85,91c
+ *
If the type of the object that you are converting is a {@code ParameterizedType}
+ * (i.e. has at least one type argument, for example {@code List}) then for
+ * deserialization you must use a {@code fromJson} method with {@link Type} or {@link TypeToken}
+ * parameter to specify the parameterized type. For serialization specifying a {@code Type}
+ * or {@code TypeToken} is optional, otherwise Gson will use the runtime type of the object.
+ * {@link TypeToken} is a class provided by Gson which helps creating parameterized types.
+ * Here is an example showing how this can be done:
+====1
+1:88,90c
+ * Type listType = new TypeToken<List<String>>() {}.getType();
+ * List<String> target = new LinkedList<String>();
+ * target.add("blah");
+2:100,102c
+3:93,95c
+ * TypeToken<List<MyType>> listType = new TypeToken<List<MyType>>() {};
+ * List<MyType> target = new LinkedList<MyType>();
+ * target.add(new MyType(1, "abc"));
+====1
+1:93,94c
+ * String json = gson.toJson(target, listType);
+ * List<String> target2 = gson.fromJson(json, listType);
+2:105,110c
+3:98,103c
+ * // For serialization you normally do not have to specify the type, Gson will use
+ * // the runtime type of the objects, however you can also specify it explicitly
+ * String json = gson.toJson(target, listType.getType());
+ *
+ * // But for deserialization you have to specify the type
+ * List<MyType> target2 = gson.fromJson(json, listType);
+====1
+1:97c
+ * See the Gson User Guide
+2:113c
+3:106c
+ *
See the Gson User Guide
+====1
+1:100c
+ * @see com.google.gson.reflect.TypeToken
+2:116,143c
+3:109,136c
+ *
Lenient JSON handling
+ * For legacy reasons most of the {@code Gson} methods allow JSON data which does not
+ * comply with the JSON specification, regardless of whether {@link GsonBuilder#setLenient()}
+ * is used or not. If this behavior is not desired, the following workarounds can be used:
+ *
+ * Serialization
+ *
+ * Use {@link #getAdapter(Class)} to obtain the adapter for the type to be serialized
+ * When using an existing {@code JsonWriter}, manually apply the writer settings of this
+ * {@code Gson} instance listed by {@link #newJsonWriter(Writer)}.
+ * Otherwise, when not using an existing {@code JsonWriter}, use {@link #newJsonWriter(Writer)}
+ * to construct one.
+ * Call {@link TypeAdapter#write(JsonWriter, Object)}
+ *
+ *
+ * Deserialization
+ *
+ * Use {@link #getAdapter(Class)} to obtain the adapter for the type to be deserialized
+ * When using an existing {@code JsonReader}, manually apply the reader settings of this
+ * {@code Gson} instance listed by {@link #newJsonReader(Reader)}.
+ * Otherwise, when not using an existing {@code JsonReader}, use {@link #newJsonReader(Reader)}
+ * to construct one.
+ * Call {@link TypeAdapter#read(JsonReader)}
+ * Call {@link JsonReader#peek()} and verify that the result is {@link JsonToken#END_DOCUMENT}
+ * to make sure there is no trailing data
+ *
+ *
+ * @see TypeToken
+====1
+1:120c
+ private static final TypeToken> NULL_KEY_SURROGATE = TypeToken.get(Object.class);
+2:162a
+3:155a
+====
+1:130,133c
+ private final ThreadLocal, FutureTypeAdapter>>> calls
+ = new ThreadLocal, FutureTypeAdapter>>>();
+
+ private final Map, TypeAdapter>> typeTokenCache = new ConcurrentHashMap, TypeAdapter>>();
+2:172,189c
+ <<<<<<< HEAD
+ // Uses LinkedHashMap because iteration order is important, see getAdapter() implementation below
+ private final ThreadLocal, TypeAdapter>>> calls = new ThreadLocal<>();
+ ||||||| 47dea2ee
+ private final ThreadLocal, FutureTypeAdapter>>> calls
+ = new ThreadLocal, FutureTypeAdapter>>>();
+ =======
+ private final ThreadLocal, FutureTypeAdapter>>> calls
+ = new ThreadLocal<>();
+ >>>>>>> TEMP_RIGHT_BRANCH
+
+ <<<<<<< HEAD
+ private final ConcurrentMap, TypeAdapter>> typeTokenCache = new ConcurrentHashMap, TypeAdapter>>();
+ ||||||| 47dea2ee
+ private final Map, TypeAdapter>> typeTokenCache = new ConcurrentHashMap, TypeAdapter>>();
+ =======
+ private final ConcurrentMap, TypeAdapter>> typeTokenCache = new ConcurrentHashMap<>();
+ >>>>>>> TEMP_RIGHT_BRANCH
+3:165,168c
+ // Uses LinkedHashMap because iteration order is important, see getAdapter() implementation below
+ private final ThreadLocal, TypeAdapter>>> calls = new ThreadLocal<>();
+
+ private final ConcurrentMap, TypeAdapter>> typeTokenCache = new ConcurrentHashMap<>();
+====1
+1:158a
+2:215c
+3:194c
+ final List reflectionFilters;
+====1
+1:185c
+ * The default field naming policy for the output Json is same as in Java. So, a Java class
+2:242c
+3:221c
+ * The default field naming policy for the output JSON is same as in Java. So, a Java class
+====1
+1:187c
+ * Json. The same rules are applied for mapping incoming Json to the Java classes. You can
+2:244c
+3:223c
+ * JSON. The same rules are applied for mapping incoming JSON to the Java classes. You can
+====1
+1:202c
+ Collections.emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY);
+2:259,260c
+3:238,239c
+ Collections.emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY,
+ Collections.emptyList());
+====1
+1:214c
+ ToNumberStrategy objectToNumberStrategy, ToNumberStrategy numberToNumberStrategy) {
+2:272,273c
+3:251,252c
+ ToNumberStrategy objectToNumberStrategy, ToNumberStrategy numberToNumberStrategy,
+ List reflectionFilters) {
+====1
+1:218c
+ this.constructorConstructor = new ConstructorConstructor(instanceCreators, useJdkUnsafe);
+2:277c
+3:256c
+ this.constructorConstructor = new ConstructorConstructor(instanceCreators, useJdkUnsafe, reflectionFilters);
+====1
+1:234a
+2:294c
+3:273c
+ this.reflectionFilters = reflectionFilters;
+====1
+1:236c
+ List factories = new ArrayList();
+2:296c
+3:275c
+ List factories = new ArrayList<>();
+====1
+1:299c
+ constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
+2:359c
+3:338c
+ constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory, reflectionFilters));
+====1
+1:308a
+2:369c
+3:348c
+ * @since 2.8.3
+====1
+1:371c
+ out.value(value);
+2:432c
+3:411c
+ out.value(doubleValue);
+====1
+1:395c
+ out.value(value);
+2:456,459c
+3:435,438c
+ // For backward compatibility don't call `JsonWriter.value(float)` because that method has
+ // been newly added and not all custom JsonWriter implementations might override it yet
+ Number floatNumber = value instanceof Float ? value : floatValue;
+ out.value(floatNumber);
+====1
+1:452c
+ List list = new ArrayList();
+2:516c
+3:495c
+ List list = new ArrayList<>();
+====1
+1:475c
+ @SuppressWarnings("unchecked")
+2:538a
+3:517a
+====1
+1:477c
+ TypeAdapter> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
+2:540,541c
+3:519,520c
+ Objects.requireNonNull(type, "type must not be null");
+ TypeAdapter> cached = typeTokenCache.get(type);
+====1
+1:479c
+ return (TypeAdapter) cached;
+2:543,545c
+3:522,524c
+ @SuppressWarnings("unchecked")
+ TypeAdapter adapter = (TypeAdapter) cached;
+ return adapter;
+====1
+1:482,483c
+ Map, FutureTypeAdapter>> threadCalls = calls.get();
+ boolean requiresThreadLocalCleanup = false;
+2:548,549c
+3:527,528c
+ LinkedHashMap, TypeAdapter>> threadCalls = calls.get();
+ boolean isInitialAdapterRequest = false;
+====
+1:485c
+ threadCalls = new HashMap, FutureTypeAdapter>>();
+2:551,557c
+ <<<<<<< HEAD
+ threadCalls = new LinkedHashMap<>();
+ ||||||| 47dea2ee
+ threadCalls = new HashMap, FutureTypeAdapter>>();
+ =======
+ threadCalls = new HashMap<>();
+ >>>>>>> TEMP_RIGHT_BRANCH
+3:530c
+ threadCalls = new LinkedHashMap<>();
+====1
+1:487c
+ requiresThreadLocalCleanup = true;
+2:559c
+3:532c
+ isInitialAdapterRequest = true;
+====
+1:491c
+ FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type);
+2:563,570c
+ <<<<<<< HEAD
+ TypeAdapter ongoingCall = (TypeAdapter) threadCalls.get(type);
+ ||||||| 47dea2ee
+ FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type);
+ =======
+ @SuppressWarnings("unchecked")
+ FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type);
+ >>>>>>> TEMP_RIGHT_BRANCH
+3:536,537c
+ @SuppressWarnings("unchecked")
+ TypeAdapter ongoingCall = (TypeAdapter) threadCalls.get(type);
+====1
+1:495a
+2:575,576c
+3:542,543c
+ int existingAdaptersCount = threadCalls.size();
+ boolean foundCandidate = false;
+====1
+1:497c
+ FutureTypeAdapter call = new FutureTypeAdapter();
+2:578c
+3:545c
+ FutureTypeAdapter call = new FutureTypeAdapter<>();
+====2
+1:502a
+3:550a
+2:584,590c
+ @SuppressWarnings("unchecked")
+ TypeAdapter existingAdapter = (TypeAdapter) typeTokenCache.putIfAbsent(type, candidate);
+ // If other thread concurrently added adapter prefer that one instead
+ if (existingAdapter != null) {
+ candidate = existingAdapter;
+ }
+
+====
+1:504c
+ typeTokenCache.put(type, candidate);
+2:592,609c
+ <<<<<<< HEAD
+ // Replace future adapter with actual adapter
+ threadCalls.put(type, candidate);
+
+ if (isInitialAdapterRequest) {
+ // Publish resolved adapters to all threads
+ // Can only do this for the initial request because cyclic dependency TypeA -> TypeB -> TypeA
+ // would otherwise publish adapter for TypeB which uses not yet resolved adapter for TypeA
+ // See https://github.com/google/gson/issues/625
+ for (Map.Entry, TypeAdapter>> resolvedAdapterEntry : threadCalls.entrySet()) {
+ typeTokenCache.putIfAbsent(resolvedAdapterEntry.getKey(), resolvedAdapterEntry.getValue());
+ }
+ }
+ foundCandidate = true;
+ ||||||| 47dea2ee
+ typeTokenCache.put(type, candidate);
+ =======
+ >>>>>>> TEMP_RIGHT_BRANCH
+3:552,570c
+ // Replace future adapter with actual adapter
+ threadCalls.put(type, candidate);
+
+ if (isInitialAdapterRequest) {
+ // Publish resolved adapters to all threads
+ // Can only do this for the initial request because cyclic dependency TypeA -> TypeB -> TypeA
+ // would otherwise publish adapter for TypeB which uses not yet resolved adapter for TypeA
+ // See https://github.com/google/gson/issues/625
+ for (Map.Entry, TypeAdapter>> resolvedAdapterEntry : threadCalls.entrySet()) {
+ typeTokenCache.putIfAbsent(resolvedAdapterEntry.getKey(), resolvedAdapterEntry.getValue());
+ }
+
+ @SuppressWarnings("unchecked")
+ TypeAdapter actualAdapter = (TypeAdapter) typeTokenCache.get(type);
+ // Prefer the actual adapter, in case putIfAbsent call above had no effect because other
+ // thread already concurrently added other adapter instance for the same type
+ candidate = actualAdapter;
+ }
+ foundCandidate = true;
+====1
+1:510,512c
+ threadCalls.remove(type);
+
+ if (requiresThreadLocalCleanup) {
+2:615c
+3:576c
+ if (isInitialAdapterRequest) {
+====
+1:514a
+2:618,635c
+ if (!foundCandidate) {
+ Iterator> adaptersIterator = threadCalls.values().iterator();
+ // Skip existing non-broken adapters
+ for (; existingAdaptersCount > 0; existingAdaptersCount--) {
+ adaptersIterator.next();
+ }
+ // Remove this future adapter and all nested ones because they might
+ // refer to broken adapters
+ while (adaptersIterator.hasNext()) {
+ TypeAdapter> brokenAdapter = adaptersIterator.next();
+ if (brokenAdapter instanceof FutureTypeAdapter) {
+ // Mark adapter as broken so user sees useful exception message in
+ // case TypeAdapterFactory leaks reference to broken adapter
+ ((FutureTypeAdapter) brokenAdapter).markBroken();
+ }
+ adaptersIterator.remove();
+ }
+ }
+3:579,596c
+ if (!foundCandidate) {
+ Iterator> adaptersIterator = threadCalls.values().iterator();
+ // Skip existing non-broken adapters
+ for (; existingAdaptersCount > 0; existingAdaptersCount--) {
+ adaptersIterator.next();
+ }
+ // Remove this future adapter and all nested ones because they might
+ // refer to broken adapters
+ while (adaptersIterator.hasNext()) {
+ TypeAdapter> brokenAdapter = adaptersIterator.next();
+ if (brokenAdapter instanceof FutureTypeAdapter) {
+ // Mark adapter as broken so user sees useful exception message in
+ // case TypeAdapterFactory leaks reference to broken adapter
+ ((FutureTypeAdapter>) brokenAdapter).markBroken();
+ }
+ adaptersIterator.remove();
+ }
+ }
+====1
+1:607c
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+2:728c
+3:689c
+ * of Java. Note that this method works fine if any of the object fields are of generic type,
+====1
+1:611,612c
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @return Json representation of {@code src}.
+2:732,733c
+3:693,694c
+ * @param src the object for which JSON representation is to be created
+ * @return JSON representation of {@code src}.
+====1
+1:613a
+2:735,736c
+3:696,697c
+ *
+ * @see #toJsonTree(Object, Type)
+====1
+1:636a
+2:760,761c
+3:721,722c
+ *
+ * @see #toJsonTree(Object)
+====1
+1:645c
+ * This method serializes the specified object into its equivalent Json representation.
+2:770c
+3:731c
+ * This method serializes the specified object into its equivalent JSON representation.
+====1
+1:649c
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+2:774c
+3:735c
+ * of Java. Note that this method works fine if any of the object fields are of generic type,
+====1
+1:654c
+ * @param src the object for which Json representation is to be created setting for Gson
+2:779c
+3:740c
+ * @param src the object for which JSON representation is to be created
+====1
+1:655a
+2:781,783c
+3:742,744c
+ *
+ * @see #toJson(Object, Appendable)
+ * @see #toJson(Object, Type)
+====1
+1:666c
+ * equivalent Json representation. This method must be used if the specified object is a generic
+2:794c
+3:755c
+ * equivalent JSON representation. This method must be used if the specified object is a generic
+====1
+1:677c
+ * @return Json representation of {@code src}
+2:805,808c
+3:766,769c
+ * @return JSON representation of {@code src}
+ *
+ * @see #toJson(Object, Type, Appendable)
+ * @see #toJson(Object)
+====1
+1:686c
+ * This method serializes the specified object into its equivalent Json representation.
+2:817,818c
+3:778,779c
+ * This method serializes the specified object into its equivalent JSON representation and
+ * writes it to the writer.
+====1
+1:690c
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+2:822c
+3:783c
+ * of Java. Note that this method works fine if any of the object fields are of generic type,
+====1
+1:694,695c
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @param writer Writer to which the Json representation needs to be written
+2:826,827c
+3:787,788c
+ * @param src the object for which JSON representation is to be created
+ * @param writer Writer to which the JSON representation needs to be written
+====1
+1:697a
+2:830,832c
+3:791,793c
+ *
+ * @see #toJson(Object)
+ * @see #toJson(Object, Type, Appendable)
+====1
+1:709,710c
+ * equivalent Json representation. This method must be used if the specified object is a generic
+ * type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
+2:844,846c
+3:805,807c
+ * equivalent JSON representation and writes it to the writer.
+ * This method must be used if the specified object is a generic type. For non-generic objects,
+ * use {@link #toJson(Object, Appendable)} instead.
+====1
+1:719c
+ * @param writer Writer to which the Json representation of src needs to be written.
+2:855c
+3:816c
+ * @param writer Writer to which the JSON representation of src needs to be written.
+====1
+1:721a
+2:858,860c
+3:819,821c
+ *
+ * @see #toJson(Object, Type)
+ * @see #toJson(Object, Appendable)
+====1
+1:734a
+2:874,882c
+3:835,843c
+ *
+ * The JSON data is written in {@linkplain JsonWriter#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided writer. The lenient mode setting
+ * of the writer is restored once this method returns.
+ *
+ *
The 'HTML-safe' and 'serialize {@code null}' settings of this {@code Gson} instance
+ * (configured by the {@link GsonBuilder}) are applied, and the original settings of the
+ * writer are restored once this method returns.
+ *
+====1
+1:737c
+ @SuppressWarnings("unchecked")
+2:884a
+3:845a
+====1
+1:739c
+ TypeAdapter> adapter = getAdapter(TypeToken.get(typeOfSrc));
+2:886,887c
+3:847,848c
+ @SuppressWarnings("unchecked")
+ TypeAdapter adapter = (TypeAdapter) getAdapter(TypeToken.get(typeOfSrc));
+====1
+1:747c
+ ((TypeAdapter) adapter).write(writer, src);
+2:895c
+3:856c
+ adapter.write(writer, src);
+====1
+1:778c
+ * @param writer Writer to which the Json representation needs to be written
+2:926c
+3:887c
+ * @param writer Writer to which the JSON representation needs to be written
+====1
+1:832a
+2:981,989c
+3:942,950c
+ *
+ * The JSON data is written in {@linkplain JsonWriter#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided writer. The lenient mode setting
+ * of the writer is restored once this method returns.
+ *
+ *
The 'HTML-safe' and 'serialize {@code null}' settings of this {@code Gson} instance
+ * (configured by the {@link GsonBuilder}) are applied, and the original settings of the
+ * writer are restored once this method returns.
+ *
+====1
+1:858c
+ * This method deserializes the specified Json into an object of the specified class. It is not
+2:1015c
+3:976c
+ * This method deserializes the specified JSON into an object of the specified class. It is not
+====1
+1:864c
+ * {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
+2:1021c
+3:982c
+ * {@link #fromJson(String, TypeToken)}. If you have the JSON in a {@link Reader} instead of
+====1
+1:866a
+2:1024,1026c
+3:985,987c
+ *
An exception is thrown if the JSON string has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is not desired.
+ *
+====1
+1:873a
+2:1034,1036c
+3:995,997c
+ *
+ * @see #fromJson(Reader, Class)
+ * @see #fromJson(String, TypeToken)
+====1
+1:876c
+ Object object = fromJson(json, (Type) classOfT);
+2:1039c
+3:1000c
+ T object = fromJson(json, TypeToken.get(classOfT));
+====1
+1:881c
+ * This method deserializes the specified Json into an object of the specified type. This method
+2:1044c
+3:1005c
+ * This method deserializes the specified JSON into an object of the specified type. This method
+====1
+1:883c
+ * {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
+2:1046c
+3:1007c
+ * {@link #fromJson(String, Class)} instead. If you have the JSON in a {@link Reader} instead of
+====1
+1:885a
+2:1049,1082c
+3:1010,1043c
+ *
Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(String, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe.
+ *
+ *
An exception is thrown if the JSON string has multiple top-level JSON elements,
+ * or if there is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is
+ * not desired.
+ *
+ * @param the type of the desired object
+ * @param json the string from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}
+ * or if {@code json} is empty.
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+ *
+ * @see #fromJson(Reader, Type)
+ * @see #fromJson(String, Class)
+ * @see #fromJson(String, TypeToken)
+ */
+ @SuppressWarnings("unchecked")
+ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
+ return (T) fromJson(json, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * This method deserializes the specified JSON into an object of the specified type. This method
+ * is useful if the specified object is a generic type. For non-generic objects, use
+ * {@link #fromJson(String, Class)} instead. If you have the JSON in a {@link Reader} instead of
+ * a String, use {@link #fromJson(Reader, TypeToken)} instead.
+ *
+ * An exception is thrown if the JSON string has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, TypeToken)} if this behavior is not desired.
+ *
+====1
+1:888,889c
+ * @param typeOfT The specific genericized type of src. You can obtain this type by using the
+ * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
+2:1085,1086c
+3:1046,1047c
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+====1
+1:892c
+ * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+2:1089c
+3:1050c
+ * new TypeToken<Collection<Foo>>(){}
+====1
+1:896,897c
+ * @throws JsonParseException if json is not a valid representation for an object of type typeOfT
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+2:1093,1097c
+3:1054,1058c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of the type typeOfT
+ *
+ * @see #fromJson(Reader, TypeToken)
+ * @see #fromJson(String, Class)
+ * @since 2.10
+====1
+1:899,900c
+ @SuppressWarnings("unchecked")
+ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
+2:1099c
+3:1060c
+ public T fromJson(String json, TypeToken typeOfT) throws JsonSyntaxException {
+====1
+1:905,906c
+ T target = (T) fromJson(reader, typeOfT);
+ return target;
+2:1104c
+3:1065c
+ return fromJson(reader, typeOfT);
+====1
+1:910c
+ * This method deserializes the Json read from the specified reader into an object of the
+2:1108c
+3:1069c
+ * This method deserializes the JSON read from the specified reader into an object of the
+====1
+1:914c
+ * this method works fine if the any of the fields of the specified object are generics, just the
+2:1112c
+3:1073c
+ * this method works fine if any of the fields of the specified object are generics, just the
+====1
+1:916c
+ * invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
+2:1114c
+3:1075c
+ * invoke {@link #fromJson(Reader, TypeToken)}. If you have the JSON in a String form instead of a
+====1
+1:918a
+2:1117,1119c
+3:1078,1080c
+ * An exception is thrown if the JSON data has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is not desired.
+ *
+====1
+1:920c
+ * @param json the reader producing the Json from which the object is to be deserialized.
+2:1121c
+3:1082c
+ * @param json the reader producing the JSON from which the object is to be deserialized.
+====1
+1:922c
+ * @return an object of type T from the string. Returns {@code null} if {@code json} is at EOF.
+2:1123c
+3:1084c
+ * @return an object of type T from the Reader. Returns {@code null} if {@code json} is at EOF.
+====1
+1:924c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+2:1125c
+3:1086c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+====1
+1:925a
+2:1127,1129c
+3:1088,1090c
+ *
+ * @see #fromJson(String, Class)
+ * @see #fromJson(Reader, TypeToken)
+====1
+1:928,930c
+ JsonReader jsonReader = newJsonReader(json);
+ Object object = fromJson(jsonReader, classOfT);
+ assertFullConsumption(object, jsonReader);
+2:1132c
+3:1093c
+ T object = fromJson(json, TypeToken.get(classOfT));
+====1
+1:935c
+ * This method deserializes the Json read from the specified reader into an object of the
+2:1137c
+3:1098c
+ * This method deserializes the JSON read from the specified reader into an object of the
+====1
+1:937c
+ * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
+2:1139c
+3:1100c
+ * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the JSON in a
+====1
+1:939a
+2:1142,1149c
+3:1103,1110c
+ *
Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(Reader, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe.
+ *
+ *
An exception is thrown if the JSON data has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, Type)} if this behavior is not desired.
+ *
+====1
+1:941,948c
+ * @param json the reader producing Json from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src. You can obtain this type by using the
+ * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is at EOF.
+2:1151,1153c
+3:1112,1114c
+ * @param json the reader producing JSON from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the Reader. Returns {@code null} if {@code json} is at EOF.
+====1
+1:950c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+2:1155c
+3:1116c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+====1
+1:951a
+2:1157,1160c
+3:1118,1121c
+ *
+ * @see #fromJson(String, Type)
+ * @see #fromJson(Reader, Class)
+ * @see #fromJson(Reader, TypeToken)
+====1
+1:954a
+2:1164,1192c
+3:1125,1153c
+ return (T) fromJson(json, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * This method deserializes the JSON read from the specified reader into an object of the
+ * specified type. This method is useful if the specified object is a generic type. For
+ * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the JSON in a
+ * String form instead of a {@link Reader}, use {@link #fromJson(String, TypeToken)} instead.
+ *
+ * An exception is thrown if the JSON data has multiple top-level JSON elements, or if there
+ * is trailing data. Use {@link #fromJson(JsonReader, TypeToken)} if this behavior is not desired.
+ *
+ * @param the type of the desired object
+ * @param json the reader producing JSON from which the object is to be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * new TypeToken<Collection<Foo>>(){}
+ *
+ * @return an object of type T from the Reader. Returns {@code null} if {@code json} is at EOF.
+ * @throws JsonIOException if there was a problem reading from the Reader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type of typeOfT
+ *
+ * @see #fromJson(String, TypeToken)
+ * @see #fromJson(Reader, Class)
+ * @since 2.10
+ */
+ public T fromJson(Reader json, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException {
+====1
+1:956c
+ T object = (T) fromJson(jsonReader, typeOfT);
+2:1194c
+3:1155c
+ T object = fromJson(jsonReader, typeOfT);
+====1
+1:964c
+ throw new JsonIOException("JSON document was not fully consumed.");
+2:1202c
+3:1163c
+ throw new JsonSyntaxException("JSON document was not fully consumed.");
+====1
+1:972a
+2:1211,1213c
+3:1172,1174c
+ // fromJson(JsonReader, Class) is unfortunately missing and cannot be added now without breaking
+ // source compatibility in certain cases, see https://github.com/google/gson/pull/1700#discussion_r973764414
+
+====1
+1:974c
+ * Reads the next JSON value from {@code reader} and convert it to an object
+2:1215c
+3:1176c
+ * Reads the next JSON value from {@code reader} and converts it to an object
+====1
+1:976c
+ * Since Type is not parameterized by T, this method is type unsafe and should be used carefully
+2:1216a
+3:1177a
+====1
+1:978,979c
+ * @throws JsonIOException if there was a problem writing to the Reader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type
+2:1218,1239c
+3:1179,1200c
+ * Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(JsonReader, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe. If the provided type is a
+ * {@code Class} the {@code TypeToken} can be created with {@link TypeToken#get(Class)}.
+ *
+ *
Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
+ * multiple top-level JSON elements, or if there is trailing data.
+ *
+ *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided reader. The lenient mode setting
+ * of the reader is restored once this method returns.
+ *
+ * @param the type of the desired object
+ * @param reader the reader whose next JSON value should be deserialized
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the JsonReader. Returns {@code null} if {@code reader} is at EOF.
+ * @throws JsonIOException if there was a problem reading from the JsonReader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+ *
+ * @see #fromJson(Reader, Type)
+ * @see #fromJson(JsonReader, TypeToken)
+====1
+1:982a
+2:1243,1276c
+3:1204,1237c
+ return (T) fromJson(reader, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * Reads the next JSON value from {@code reader} and converts it to an object
+ * of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF.
+ * This method is useful if the specified object is a generic type. For non-generic objects,
+ * {@link #fromJson(JsonReader, Type)} can be called, or {@link TypeToken#get(Class)} can
+ * be used to create the type token.
+ *
+ * Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
+ * multiple top-level JSON elements, or if there is trailing data.
+ *
+ *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
+ * regardless of the lenient mode setting of the provided reader. The lenient mode setting
+ * of the reader is restored once this method returns.
+ *
+ * @param the type of the desired object
+ * @param reader the reader whose next JSON value should be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * new TypeToken<Collection<Foo>>(){}
+ *
+ * @return an object of type T from the JsonReader. Returns {@code null} if {@code reader} is at EOF.
+ * @throws JsonIOException if there was a problem reading from the JsonReader
+ * @throws JsonSyntaxException if json is not a valid representation for an object of the type typeOfT
+ *
+ * @see #fromJson(Reader, TypeToken)
+ * @see #fromJson(JsonReader, Type)
+ * @since 2.10
+ */
+ public T fromJson(JsonReader reader, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException {
+====1
+1:989,990c
+ TypeToken typeToken = (TypeToken) TypeToken.get(typeOfT);
+ TypeAdapter typeAdapter = getAdapter(typeToken);
+2:1283c
+3:1244c
+ TypeAdapter typeAdapter = getAdapter(typeOfT);
+====1
+1:1017c
+ * This method deserializes the Json read from the specified parse tree into an object of the
+2:1310c
+3:1271c
+ * This method deserializes the JSON read from the specified parse tree into an object of the
+====1
+1:1021c
+ * this method works fine if the any of the fields of the specified object are generics, just the
+2:1314c
+3:1275c
+ * this method works fine if any of the fields of the specified object are generics, just the
+====1
+1:1023c
+ * invoke {@link #fromJson(JsonElement, Type)}.
+2:1316,1317c
+3:1277,1278c
+ * invoke {@link #fromJson(JsonElement, TypeToken)}.
+ *
+====1
+1:1028c
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}
+2:1322c
+3:1283c
+ * @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
+====1
+1:1030c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+2:1324c
+3:1285c
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type classOfT
+====1
+1:1031a
+2:1326,1328c
+3:1287,1289c
+ *
+ * @see #fromJson(Reader, Class)
+ * @see #fromJson(JsonElement, TypeToken)
+====1
+1:1034c
+ Object object = fromJson(json, (Type) classOfT);
+2:1331c
+3:1292c
+ T object = fromJson(json, TypeToken.get(classOfT));
+====1
+1:1039c
+ * This method deserializes the Json read from the specified parse tree into an object of the
+2:1336c
+3:1297c
+ * This method deserializes the JSON read from the specified parse tree into an object of the
+====1
+1:1042a
+2:1340,1344c
+3:1301,1305c
+ * Since {@code Type} is not parameterized by T, this method is not type-safe and
+ * should be used carefully. If you are creating the {@code Type} from a {@link TypeToken},
+ * prefer using {@link #fromJson(JsonElement, TypeToken)} instead since its return type is based
+ * on the {@code TypeToken} and is therefore more type-safe.
+ *
+====1
+1:1046,1052c
+ * @param typeOfT The specific genericized type of src. You can obtain this type by using the
+ * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}
+2:1348,1349c
+3:1309,1310c
+ * @param typeOfT The specific genericized type of src
+ * @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
+====1
+1:1055a
+2:1353,1356c
+3:1314,1317c
+ *
+ * @see #fromJson(Reader, Type)
+ * @see #fromJson(JsonElement, Class)
+ * @see #fromJson(JsonElement, TypeToken)
+====1
+1:1058a
+2:1360,1385c
+3:1321,1346c
+ return (T) fromJson(json, TypeToken.get(typeOfT));
+ }
+
+ /**
+ * This method deserializes the JSON read from the specified parse tree into an object of the
+ * specified type. This method is useful if the specified object is a generic type. For
+ * non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
+ *
+ * @param the type of the desired object
+ * @param json the root of the parse tree of {@link JsonElement}s from which the object is to
+ * be deserialized
+ * @param typeOfT The specific genericized type of src. You should create an anonymous subclass of
+ * {@code TypeToken} with the specific generic type arguments. For example, to get the type for
+ * {@code Collection}, you should use:
+ *
+ * new TypeToken<Collection<Foo>>(){}
+ *
+ * @return an object of type T from the JSON. Returns {@code null} if {@code json} is {@code null}
+ * or if {@code json} is empty.
+ * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
+ *
+ * @see #fromJson(Reader, TypeToken)
+ * @see #fromJson(JsonElement, Class)
+ * @since 2.10
+ */
+ public T fromJson(JsonElement json, TypeToken typeOfT) throws JsonSyntaxException {
+====1
+1:1062c
+ return (T) fromJson(new JsonTreeReader(json), typeOfT);
+2:1389c
+3:1350c
+ return fromJson(new JsonTreeReader(json), typeOfT);
+====
+1:1065,1066c
+ static class FutureTypeAdapter extends TypeAdapter {
+ private TypeAdapter delegate;
+2:1392,1402c
+ <<<<<<< HEAD
+ static class FutureTypeAdapter extends TypeAdapter {
+ private TypeAdapter delegate = null;
+ private boolean isBroken = false;
+ ||||||| 47dea2ee
+ static class FutureTypeAdapter extends TypeAdapter {
+ private TypeAdapter delegate;
+ =======
+ static class FutureTypeAdapter extends SerializationDelegatingTypeAdapter {
+ private TypeAdapter delegate;
+ >>>>>>> TEMP_RIGHT_BRANCH
+3:1353,1355c
+ static class FutureTypeAdapter extends SerializationDelegatingTypeAdapter {
+ private TypeAdapter delegate = null;
+ private boolean isBroken = false;
+====
+1:1075c
+ @Override public T read(JsonReader in) throws IOException {
+2:1411,1430c
+ <<<<<<< HEAD
+ public void markBroken() {
+ isBroken = true;
+ }
+
+ private TypeAdapter getResolvedDelegate() {
+ TypeAdapter delegate = this.delegate;
+ if (isBroken) {
+ throw new IllegalStateException("Broken adapter has been leaked by TypeAdapterFactory");
+ ||||||| 47dea2ee
+ @Override public T read(JsonReader in) throws IOException {
+ if (delegate == null) {
+ throw new IllegalStateException();
+ =======
+ private TypeAdapter delegate() {
+ if (delegate == null) {
+ throw new IllegalStateException("Delegate has not been set yet");
+ >>>>>>> TEMP_RIGHT_BRANCH
+ }
+ <<<<<<< HEAD
+3:1364,1372c
+ public void markBroken() {
+ isBroken = true;
+ }
+
+ private TypeAdapter delegate() {
+ TypeAdapter