1 /* ide-foundry-compat.c
2  *
3  * Copyright 2018-2019 Christian Hergert <chergert@redhat.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * SPDX-License-Identifier: GPL-3.0-or-later
19  */
20 
21 #define G_LOG_DOMAIN "ide-foundry-compat"
22 
23 #include "config.h"
24 
25 #include "ide-build-manager.h"
26 #include "ide-build-system.h"
27 #include "ide-device-manager.h"
28 #include "ide-config-manager.h"
29 #include "ide-foundry-compat.h"
30 #include "ide-run-manager.h"
31 #include "ide-runtime-manager.h"
32 #include "ide-test-manager.h"
33 #include "ide-toolchain-manager.h"
34 
35 static gpointer
ensure_child_typed_borrowed(IdeContext * context,GType child_type)36 ensure_child_typed_borrowed (IdeContext *context,
37                              GType       child_type)
38 {
39   gpointer ret;
40 
41   if (!IDE_IS_MAIN_THREAD ())
42     {
43       IDE_BACKTRACE;
44 
45       g_error ("A plugin has attempted to access child of type %s on a thread without referencing. "
46                "This is not allowed and the application will terminate.",
47                g_type_name (child_type));
48     }
49 
50   g_assert (IDE_IS_MAIN_THREAD ());
51   g_assert (IDE_IS_CONTEXT (context));
52 
53   if (!(ret = ide_context_peek_child_typed (context, child_type)))
54     {
55       g_autoptr(IdeObject) child = NULL;
56 
57       if (!ide_context_has_project (context))
58         {
59           g_critical ("A plugin has attempted to access the %s foundry subsystem before a project has been loaded. "
60                       "This is not supported and may cause undesired behavior.",
61                       g_type_name (child_type));
62         }
63 
64       child = ide_object_ensure_child_typed (IDE_OBJECT (context), child_type);
65       ret = ide_context_peek_child_typed (context, child_type);
66     }
67 
68   return ret;
69 }
70 
71 static gpointer
get_child_typed_borrowed(IdeContext * context,GType child_type)72 get_child_typed_borrowed (IdeContext *context,
73                           GType       child_type)
74 {
75   GObject *ret;
76 
77   g_assert (IDE_IS_MAIN_THREAD ());
78   g_assert (IDE_IS_CONTEXT (context));
79 
80   /* We get a full ref to the child, but we want to return a borrowed
81    * reference to the manager. Since we're on the main thread, we can
82    * guarantee that no destroy will happen (since that has to happen
83    * in the main thread).
84    */
85   if ((ret = ide_object_get_child_typed (IDE_OBJECT (context), child_type)))
86     g_object_unref (ret);
87 
88   return ret;
89 }
90 
91 /**
92  * ide_build_manager_from_context:
93  * @context: a #IdeContext
94  *
95  * Returns: (transfer none): an #IdeBuildManager
96  *
97  * Since: 3.32
98  */
99 IdeBuildManager *
ide_build_manager_from_context(IdeContext * context)100 ide_build_manager_from_context (IdeContext *context)
101 {
102   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
103 
104   return ensure_child_typed_borrowed (context, IDE_TYPE_BUILD_MANAGER);
105 }
106 
107 /**
108  * ide_build_manager_ref_from_context:
109  * @context: a #IdeContext
110  *
111  * Returns: (transfer full): an #IdeBuildManager
112  *
113  * Since: 3.32
114  */
115 IdeBuildManager *
ide_build_manager_ref_from_context(IdeContext * context)116 ide_build_manager_ref_from_context (IdeContext *context)
117 {
118   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
119 
120   return ide_object_ensure_child_typed (IDE_OBJECT (context), IDE_TYPE_BUILD_MANAGER);
121 }
122 
123 /**
124  * ide_build_system_from_context:
125  * @context: a #IdeContext
126  *
127  * Gets the build system for the context. If no build system has been
128  * registered, then this returns %NULL.
129  *
130  * Returns: (transfer none) (nullable): an #IdeBuildSystem
131  *
132  * Since: 3.32
133  */
134 IdeBuildSystem *
ide_build_system_from_context(IdeContext * context)135 ide_build_system_from_context (IdeContext *context)
136 {
137   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
138 
139   return get_child_typed_borrowed (context, IDE_TYPE_BUILD_SYSTEM);
140 }
141 
142 /**
143  * ide_config_manager_from_context:
144  * @context: a #IdeContext
145  *
146  * Returns: (transfer none): an #IdeConfigManager
147  *
148  * Since: 3.32
149  */
150 IdeConfigManager *
ide_config_manager_from_context(IdeContext * context)151 ide_config_manager_from_context (IdeContext *context)
152 {
153   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
154 
155   return ensure_child_typed_borrowed (context, IDE_TYPE_CONFIG_MANAGER);
156 }
157 
158 /**
159  * ide_device_manager_from_context:
160  * @context: a #IdeContext
161  *
162  * Returns: (transfer none): an #IdeDeviceManager
163  *
164  * Since: 3.32
165  */
166 IdeDeviceManager *
ide_device_manager_from_context(IdeContext * context)167 ide_device_manager_from_context (IdeContext *context)
168 {
169   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
170 
171   return ensure_child_typed_borrowed (context, IDE_TYPE_DEVICE_MANAGER);
172 }
173 
174 /**
175  * ide_toolchain_manager_from_context:
176  * @context: a #IdeContext
177  *
178  * Returns: (transfer none): an #IdeToolchainManager
179  *
180  * Since: 3.32
181  */
182 IdeToolchainManager *
ide_toolchain_manager_from_context(IdeContext * context)183 ide_toolchain_manager_from_context (IdeContext *context)
184 {
185   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
186 
187   return ensure_child_typed_borrowed (context, IDE_TYPE_TOOLCHAIN_MANAGER);
188 }
189 
190 /**
191  * ide_run_manager_from_context:
192  * @context: a #IdeContext
193  *
194  * Returns: (transfer none): an #IdeRunManager
195  *
196  * Since: 3.32
197  */
198 IdeRunManager *
ide_run_manager_from_context(IdeContext * context)199 ide_run_manager_from_context (IdeContext *context)
200 {
201   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
202 
203   return ensure_child_typed_borrowed (context, IDE_TYPE_RUN_MANAGER);
204 }
205 
206 /**
207  * ide_runtime_manager_from_context:
208  * @context: a #IdeContext
209  *
210  * Returns: (transfer none): an #IdeRuntimeManager
211  *
212  * Since: 3.32
213  */
214 IdeRuntimeManager *
ide_runtime_manager_from_context(IdeContext * context)215 ide_runtime_manager_from_context (IdeContext *context)
216 {
217   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
218 
219   return ensure_child_typed_borrowed (context, IDE_TYPE_RUNTIME_MANAGER);
220 }
221 
222 /**
223  * ide_test_manager_from_context:
224  * @context: a #IdeContext
225  *
226  * Returns: (transfer none): an #IdeTestManager
227  *
228  * Since: 3.32
229  */
230 IdeTestManager *
ide_test_manager_from_context(IdeContext * context)231 ide_test_manager_from_context (IdeContext *context)
232 {
233   g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
234 
235   return ensure_child_typed_borrowed (context, IDE_TYPE_TEST_MANAGER);
236 }
237