These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | use SMW\ApplicationFactory; |
||
4 | use SMW\DataValueFactory; |
||
5 | use SMW\DIProperty; |
||
6 | use SMW\Highlighter; |
||
7 | use SMW\Message; |
||
8 | |||
9 | /** |
||
10 | * Objects of this class represent properties in SMW. |
||
11 | * |
||
12 | * This class represents both normal (user-defined) properties and |
||
13 | * predefined ("special") properties. Predefined properties may still |
||
14 | * have a standard label (and associated wiki article) and they will |
||
15 | * behave just like user-defined properties in most cases (e.g. when |
||
16 | * asking for a printout text, a link to the according page is produced). |
||
17 | * It is possible that predefined properties have no visible label at all, |
||
18 | * if they are used only internally and never specified by or shown to |
||
19 | * the user. Those will use their internal ID as DB key, and |
||
20 | * empty texts for most printouts. All other proeprties use their |
||
21 | * canonical DB key (even if they are predefined and have an id). |
||
22 | * Functions are provided to check whether a property is visible or |
||
23 | * user-defined, and to get the internal ID, if any. |
||
24 | * |
||
25 | * @note This datavalue is used only for representing properties and, |
||
26 | * possibly objects/values, but never for subjects (pages as such). Hence |
||
27 | * it does not provide a complete Title-like interface, or support for |
||
28 | * things like sortkey. |
||
29 | * |
||
30 | * @author Markus Krötzsch |
||
31 | * @ingroup SMWDataValues |
||
32 | */ |
||
33 | class SMWPropertyValue extends SMWDataValue { |
||
34 | |||
35 | /** |
||
36 | * Cache for wiki page value object associated to this property, or |
||
37 | * null if no such page exists. Use getWikiPageValue() to get the data. |
||
38 | * @var SMWWikiPageValue |
||
39 | */ |
||
40 | protected $m_wikipage = null; |
||
41 | |||
42 | /** |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $linkAttributes = array(); |
||
46 | |||
47 | /** |
||
48 | * Cache for type value of this property, or null if not calculated yet. |
||
49 | * @var SMWTypesValue |
||
50 | */ |
||
51 | private $mPropTypeValue; |
||
52 | |||
53 | /** |
||
54 | * @var DIProperty |
||
55 | */ |
||
56 | private $inceptiveProperty = null; |
||
57 | |||
58 | /** |
||
59 | * @since 2.4 |
||
60 | * |
||
61 | * @param string $typeid |
||
62 | */ |
||
63 | 218 | public function __construct( $typeid ) { |
|
64 | 218 | parent::__construct( $typeid ); |
|
65 | 218 | } |
|
66 | |||
67 | /** |
||
68 | * Static function for creating a new property object from a |
||
69 | * propertyname (string) as a user might enter it. |
||
70 | * @note The resulting property object might be invalid if |
||
71 | * the provided name is not allowed. An object is returned |
||
72 | * in any case. |
||
73 | * |
||
74 | * @param string $propertyName |
||
0 ignored issues
–
show
|
|||
75 | * |
||
76 | * @return SMWPropertyValue |
||
77 | */ |
||
78 | 131 | static public function makeUserProperty( $propertyLabel ) { |
|
79 | 131 | return DataValueFactory::getInstance()->newPropertyValueByLabel( $propertyLabel ); |
|
80 | } |
||
81 | |||
82 | /** |
||
83 | * Static function for creating a new property object from a property |
||
84 | * identifier (string) as it might be used internally. This might be |
||
85 | * the DB key version of some property title text or the id of a |
||
86 | * predefined property (such as '_TYPE'). |
||
87 | * @note This function strictly requires an internal identifier, i.e. |
||
88 | * predefined properties must be referred to by their ID, and '-' is |
||
89 | * not supported for indicating inverses. |
||
90 | * @note The resulting property object might be invalid if |
||
91 | * the provided name is not allowed. An object is returned |
||
92 | * in any case. |
||
93 | */ |
||
94 | static public function makeProperty( $propertyid ) { |
||
0 ignored issues
–
show
|
|||
95 | $diProperty = new DIProperty( $propertyid ); |
||
96 | $dvProperty = new SMWPropertyValue( '__pro' ); |
||
97 | $dvProperty->setDataItem( $diProperty ); |
||
98 | return $dvProperty; |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * We use the internal wikipage object to store some of this objects data. |
||
103 | * Clone it to make sure that data can be modified independently from the |
||
104 | * original object's content. |
||
105 | */ |
||
106 | 1 | public function __clone() { |
|
107 | 1 | if ( !is_null( $this->m_wikipage ) ) { |
|
108 | 1 | $this->m_wikipage = clone $this->m_wikipage; |
|
109 | } |
||
110 | 1 | } |
|
111 | |||
112 | /** |
||
113 | * @note If the inceptive property and the property referenced in dataItem |
||
114 | * are not equal then the dataItem represents the end target to which the |
||
115 | * inceptive property has been redirected. |
||
116 | * |
||
117 | * @since 2.4 |
||
118 | * |
||
119 | * @return DIProperty |
||
120 | */ |
||
121 | 1 | public function getInceptiveProperty() { |
|
122 | 1 | return $this->inceptiveProperty; |
|
123 | } |
||
124 | |||
125 | /** |
||
126 | * Extended parsing function to first check whether value refers to pre-defined |
||
127 | * property, resolve aliases, and set internal property id accordingly. |
||
128 | * @todo Accept/enforce property namespace. |
||
129 | */ |
||
130 | 199 | protected function parseUserValue( $value ) { |
|
131 | 199 | $this->mPropTypeValue = null; |
|
132 | 199 | $this->m_wikipage = null; |
|
133 | |||
134 | 199 | if ( $this->m_caption === false ) { // always use this as caption |
|
135 | 199 | $this->m_caption = $value; |
|
136 | } |
||
137 | |||
138 | 199 | list( $propertyName, $inverse ) = $this->doNormalizeUserValue( |
|
139 | $value |
||
140 | ); |
||
141 | |||
142 | 199 | $contentLanguage = $this->getOptionBy( self::OPT_CONTENT_LANGUAGE ); |
|
143 | |||
144 | try { |
||
145 | 199 | $this->m_dataitem = DIProperty::newFromUserLabel( $propertyName, $inverse, $contentLanguage ); |
|
146 | 2 | } catch ( SMWDataItemException $e ) { // happens, e.g., when trying to sort queries by property "-" |
|
147 | 2 | $this->addErrorMsg( array( 'smw_noproperty', $value ) ); |
|
148 | 2 | $this->m_dataitem = new DIProperty( 'ERROR', false ); // just to have something |
|
149 | } |
||
150 | |||
151 | // @see the SMW_DV_PROV_DTITLE explanation |
||
152 | 199 | if ( $this->isEnabledFeature( SMW_DV_PROV_DTITLE ) ) { |
|
153 | $dataItem = ApplicationFactory::getInstance()->getPropertySpecificationLookup()->getPropertyFromDisplayTitle( |
||
154 | $value |
||
155 | ); |
||
156 | |||
157 | $this->m_dataitem = $dataItem ? $dataItem : $this->m_dataitem; |
||
158 | } |
||
159 | |||
160 | 199 | $this->inceptiveProperty = $this->m_dataitem; |
|
161 | |||
162 | 199 | if ( $this->isEnabledFeature( SMW_DV_PROV_REDI ) ) { |
|
163 | 191 | $this->m_dataitem = $this->m_dataitem->getRedirectTarget(); |
|
164 | } |
||
165 | 199 | } |
|
166 | |||
167 | /** |
||
168 | * @see SMWDataValue::loadDataItem() |
||
169 | * @param $dataitem SMWDataItem |
||
170 | * @return boolean |
||
171 | */ |
||
172 | 32 | protected function loadDataItem( SMWDataItem $dataItem ) { |
|
173 | |||
174 | 32 | if ( $dataItem->getDIType() !== SMWDataItem::TYPE_PROPERTY ) { |
|
175 | return false; |
||
176 | } |
||
177 | |||
178 | 32 | $this->inceptiveProperty = $dataItem; |
|
179 | 32 | $this->m_dataitem = $dataItem; |
|
180 | |||
181 | 32 | $this->mPropTypeValue = null; |
|
182 | 32 | unset( $this->m_wikipage ); |
|
183 | 32 | $this->m_caption = false; |
|
184 | 32 | $this->linkAttributes = array(); |
|
185 | |||
186 | 32 | return true; |
|
187 | } |
||
188 | |||
189 | /** |
||
190 | * @since 2.4 |
||
191 | * |
||
192 | * @param array $linkAttributes |
||
193 | */ |
||
194 | 1 | public function setLinkAttributes( array $linkAttributes ) { |
|
195 | 1 | $this->linkAttributes = $linkAttributes; |
|
196 | |||
197 | 1 | if ( $this->getWikiPageValue() instanceof SMWDataValue ) { |
|
198 | 1 | $this->m_wikipage->setLinkAttributes( $linkAttributes ); |
|
199 | } |
||
200 | 1 | } |
|
201 | |||
202 | 105 | public function setCaption( $caption ) { |
|
203 | 105 | parent::setCaption( $caption ); |
|
204 | 105 | if ( $this->getWikiPageValue() instanceof SMWDataValue ) { // pass caption to embedded datavalue (used for printout) |
|
205 | 105 | $this->m_wikipage->setCaption( $caption ); |
|
206 | } |
||
207 | 105 | } |
|
208 | |||
209 | public function setOutputFormat( $formatstring ) { |
||
210 | $this->m_outformat = $formatstring; |
||
211 | if ( $this->m_wikipage instanceof SMWDataValue ) { |
||
212 | $this->m_wikipage->setOutputFormat( $formatstring ); |
||
213 | } |
||
214 | } |
||
215 | |||
216 | public function setInverse( $isinverse ) { |
||
217 | return $this->m_dataitem = new DIProperty( $this->m_dataitem->getKey(), ( $isinverse == true ) ); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Return a wiki page value that can be used for displaying this |
||
222 | * property, or null if no such wiki page exists (for predefined |
||
223 | * properties without any label). |
||
224 | * @return SMWWikiPageValue or null |
||
225 | */ |
||
226 | 109 | public function getWikiPageValue() { |
|
227 | |||
228 | 109 | if ( isset( $this->m_wikipage ) ) { |
|
229 | 69 | return $this->m_wikipage; |
|
230 | } |
||
231 | |||
232 | 109 | $diWikiPage = $this->m_dataitem->getCanonicalDiWikiPage(); |
|
233 | |||
234 | 109 | if ( $diWikiPage !== null ) { |
|
235 | 109 | $this->m_wikipage = \SMW\DataValueFactory::getInstance()->newDataValueByItem( $diWikiPage, null, $this->m_caption ); |
|
236 | 109 | $this->m_wikipage->setOutputFormat( $this->m_outformat ); |
|
237 | 109 | $this->m_wikipage->setLinkAttributes( $this->linkAttributes ); |
|
238 | 109 | $this->m_wikipage->setOptions( $this->getOptions() ); |
|
239 | 109 | $this->addError( $this->m_wikipage->getErrors() ); |
|
240 | } else { // should rarely happen ($value is only changed if the input $value really was a label for a predefined prop) |
||
241 | $this->m_wikipage = null; |
||
242 | } |
||
243 | |||
244 | 109 | return $this->m_wikipage; |
|
245 | } |
||
246 | |||
247 | /** |
||
248 | * Return TRUE if this is a property that can be displayed, and not a pre-defined |
||
249 | * property that is used only internally and does not even have a user-readable name. |
||
250 | * @note Every user defined property is necessarily visible. |
||
251 | */ |
||
252 | 94 | public function isVisible() { |
|
253 | 94 | return $this->isValid() && ( $this->m_dataitem->isUserDefined() || $this->m_dataitem->getLabel() !== '' ); |
|
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
SMWDataItem as the method isUserDefined() does only exist in the following sub-classes of SMWDataItem : SMWDIProperty , SMW\DIProperty . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
It seems like you code against a specific sub-type and not the parent class
SMWDataItem as the method getLabel() does only exist in the following sub-classes of SMWDataItem : SMWDIProperty , SMW\DIProperty . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
254 | } |
||
255 | |||
256 | /** |
||
257 | * @since 2.2 |
||
258 | * |
||
259 | * @return boolean |
||
260 | */ |
||
261 | 177 | public function canUse() { |
|
262 | 177 | return $this->isValid() && $this->m_dataitem->isUnrestricted(); |
|
263 | } |
||
264 | |||
265 | 40 | public function getShortWikiText( $linked = null ) { |
|
266 | |||
267 | 40 | if ( $this->isVisible() ) { |
|
268 | 39 | $wikiPageValue = $this->getWikiPageValue(); |
|
269 | 39 | return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getShortWikiText( $linked ) ); |
|
270 | } |
||
271 | |||
272 | 1 | return ''; |
|
273 | } |
||
274 | |||
275 | 6 | public function getShortHTMLText( $linked = null ) { |
|
276 | |||
277 | 6 | if ( $this->isVisible() ) { |
|
278 | 6 | $wikiPageValue = $this->getWikiPageValue(); |
|
279 | 6 | return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getShortHTMLText( $linked ), $linked ); |
|
280 | } |
||
281 | |||
282 | return ''; |
||
283 | } |
||
284 | |||
285 | 12 | public function getLongWikiText( $linked = null ) { |
|
286 | |||
287 | 12 | if ( $this->isVisible() ) { |
|
288 | 12 | $wikiPageValue = $this->getWikiPageValue(); |
|
289 | 12 | return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getLongWikiText( $linked ) ); |
|
290 | } |
||
291 | |||
292 | return ''; |
||
293 | } |
||
294 | |||
295 | public function getLongHTMLText( $linked = null ) { |
||
296 | |||
297 | if ( $this->isVisible() ) { |
||
298 | $wikiPageValue = $this->getWikiPageValue(); |
||
299 | return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getLongHTMLText( $linked ), $linked ); |
||
300 | } |
||
301 | |||
302 | return ''; |
||
303 | } |
||
304 | |||
305 | 68 | public function getWikiValue() { |
|
306 | |||
307 | 68 | if ( !$this->isVisible() ) { |
|
308 | return ''; |
||
309 | } |
||
310 | |||
311 | 68 | if ( $this->getWikiPageValue() !== null && $this->getWikiPageValue()->getDisplayTitle() !== '' ) { |
|
312 | 1 | return $this->getWikiPageValue()->getDisplayTitle(); |
|
313 | } |
||
314 | |||
315 | 68 | return $this->m_dataitem->getLabel(); |
|
316 | } |
||
317 | |||
318 | /** |
||
319 | * If this property was not user defined, return the internal ID string referring to |
||
320 | * that property. Otherwise return FALSE; |
||
321 | */ |
||
322 | public function getPropertyID() { |
||
323 | return $this->m_dataitem->isUserDefined() ? false : $this->m_dataitem->getKey(); |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Return an SMWTypesValue object representing the datatype of this |
||
328 | * property. |
||
329 | * @deprecated Types values are not a good way to exchange SMW type information. They are for input only. Use getPropertyTypeID() if you want the type id. This method will vanish in SMW 1.7. |
||
330 | */ |
||
331 | public function getTypesValue() { |
||
332 | $result = SMWTypesValue::newFromTypeId( $this->getPropertyTypeID() ); |
||
333 | if ( !$this->isValid() ) { |
||
334 | $result->addError( $this->getErrors() ); |
||
335 | } |
||
336 | return $result; |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Convenience method to find the type id of this property. Most callers |
||
341 | * should rather use DIProperty::findPropertyTypeId() directly. Note |
||
342 | * that this is not the same as getTypeID(), which returns the id of |
||
343 | * this property datavalue. |
||
344 | * |
||
345 | * @return string |
||
346 | */ |
||
347 | 4 | public function getPropertyTypeID() { |
|
348 | 4 | if ( $this->isValid() ) { |
|
349 | 4 | return $this->m_dataitem->findPropertyTypeId(); |
|
350 | } else { |
||
351 | return '__err'; |
||
352 | } |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * Create special highlighting for hinting at special properties. |
||
357 | */ |
||
358 | 51 | protected function highlightText( $text, $linker = null ) { |
|
359 | |||
360 | 51 | $propertySpecificationLookup = ApplicationFactory::getInstance()->getPropertySpecificationLookup(); |
|
361 | |||
362 | 51 | if ( ( $content = $propertySpecificationLookup->getPropertyDescriptionBy( $this->m_dataitem, $linker ) ) !== '' || !$this->m_dataitem->isUserDefined() ) { |
|
363 | |||
364 | 14 | $highlighter = Highlighter::factory( Highlighter::TYPE_PROPERTY ); |
|
365 | 14 | $highlighter->setContent( array ( |
|
366 | 14 | 'userDefined' => $this->m_dataitem->isUserDefined(), |
|
367 | 14 | 'caption' => $text, |
|
368 | 14 | 'content' => $content !== '' ? $content : wfMessage( 'smw_isspecprop' )->text() |
|
369 | ) ); |
||
370 | |||
371 | 14 | return $highlighter->getHtml(); |
|
372 | } |
||
373 | |||
374 | 46 | return $text; |
|
375 | } |
||
376 | |||
377 | /** |
||
378 | * A function for registering/overwriting predefined properties for SMW. Should be called from |
||
379 | * within the hook 'smwInitProperties'. Ids should start with three underscores "___" to avoid |
||
380 | * current and future confusion with SMW built-ins. |
||
381 | * |
||
382 | * @deprecated Use DIProperty::registerProperty(). Will vanish before SMW 1.7. |
||
383 | */ |
||
384 | static public function registerProperty( $id, $typeid, $label = false, $show = false ) { |
||
385 | DIProperty::registerProperty( $id, $typeid, $label, $show ); |
||
386 | } |
||
387 | |||
388 | /** |
||
389 | * Add a new alias label to an existing datatype id. Note that every ID should have a primary |
||
390 | * label, either provided by SMW or registered with registerDatatype. This function should be |
||
391 | * called from within the hook 'smwInitDatatypes'. |
||
392 | * |
||
393 | * @deprecated Use DIProperty::registerPropertyAlias(). Will vanish before SMW 1.7. |
||
394 | */ |
||
395 | static public function registerPropertyAlias( $id, $label ) { |
||
396 | DIProperty::registerPropertyAlias( $id, $label ); |
||
397 | } |
||
398 | |||
399 | /** |
||
400 | * @see DIProperty::isUserDefined() |
||
401 | * |
||
402 | * @deprecated since 1.6 |
||
403 | */ |
||
404 | public function isUserDefined() { |
||
405 | return $this->m_dataitem->isUserDefined(); |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * @see DIProperty::isShown() |
||
410 | * |
||
411 | * @deprecated since 1.6 |
||
412 | */ |
||
413 | public function isShown() { |
||
414 | return $this->m_dataitem->isShown(); |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * @see DIProperty::isInverse() |
||
419 | * |
||
420 | * @deprecated since 1.6 |
||
421 | */ |
||
422 | public function isInverse() { |
||
423 | return $this->m_dataitem->isInverse(); |
||
424 | } |
||
425 | |||
426 | /** |
||
427 | * Return a DB-key-like string: for visible properties, it is the actual DB key, |
||
428 | * for internal (invisible) properties, it is the property ID. The value agrees |
||
429 | * with the first component of getDBkeys() and it can be used in its place. |
||
430 | * @see DIProperty::getKey() |
||
431 | * |
||
432 | * @deprecated since 1.6 |
||
433 | */ |
||
434 | public function getDBkey() { |
||
435 | return $this->m_dataitem->getKey(); |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * @see DIProperty::getLabel() |
||
440 | * |
||
441 | * @deprecated since 1.6 |
||
442 | */ |
||
443 | public function getText() { |
||
444 | return $this->m_dataitem->getLabel(); |
||
445 | } |
||
446 | |||
447 | 199 | private function doNormalizeUserValue( $value ) { |
|
448 | |||
449 | if ( |
||
450 | 199 | ( $pos = strpos( $value, '#' ) ) !== false && strlen( $value ) > 1 || /* #1567 */ |
|
451 | 199 | ( $pos = strpos( $value, '[' ) ) !== false ) /* #1638 */ { |
|
452 | 2 | $this->addErrorMsg( array( 'smw-datavalue-property-invalid-name', $value, substr( $value, $pos, 1 ) ) ); |
|
453 | 2 | $this->m_dataitem = new DIProperty( 'ERROR', false ); |
|
454 | } |
||
455 | |||
456 | // #1727 <Foo> or <Foo-<Bar> are not permitted but |
||
457 | // Foo-<Bar will be converted to Foo- |
||
458 | 199 | $value = strip_tags( htmlspecialchars_decode( $value ) ); |
|
459 | 199 | $inverse = false; |
|
460 | |||
461 | // Enforce upper case for the first character on annotations that are used |
||
462 | // within the property namespace in order to avoid confusion when |
||
463 | // $wgCapitalLinks setting is disabled |
||
464 | 199 | if ( $this->getContextPage() !== null && $this->getContextPage()->getNamespace() === SMW_NS_PROPERTY ) { |
|
465 | // ucfirst is not utf-8 safe hence the reliance on mb_strtoupper |
||
466 | 141 | $value = mb_strtoupper( mb_substr( $value, 0, 1 ) ) . mb_substr( $value, 1 ); |
|
467 | } |
||
468 | |||
469 | // slightly normalise label |
||
470 | 199 | $propertyName = smwfNormalTitleText( ltrim( rtrim( $value, ' ]' ), ' [' ) ); |
|
471 | |||
472 | 199 | if ( ( $propertyName !== '' ) && ( $propertyName { 0 } == '-' ) ) { // property refers to an inverse |
|
473 | 11 | $propertyName = smwfNormalTitleText( (string)substr( $value, 1 ) ); |
|
474 | /// NOTE The cast is necessary at least in PHP 5.3.3 to get string '' instead of boolean false. |
||
475 | /// NOTE It is necessary to normalize again here, since normalization may uppercase the first letter. |
||
476 | 11 | $inverse = true; |
|
477 | } |
||
478 | |||
479 | 199 | return array( $propertyName, $inverse ); |
|
480 | } |
||
481 | |||
482 | } |
||
483 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italy
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was removed, but the annotation was not.