[#25] Moved MethodBuilder property validation into MemberBuilderValidator
- Tests have not yet been movedclosure/master
parent
5e46298e39
commit
a91cb01998
|
@ -175,57 +175,12 @@ exports.buildProp = function( members, meta, name, value, keywords, base )
|
|||
// TODO: We can improve performance by not scanning each one individually
|
||||
// every time this method is called
|
||||
var prev_data = scanMembers( members, name, base ),
|
||||
prev = ( prev_data ) ? prev_data.member : null;
|
||||
prev = ( prev_data ) ? prev_data.member : null,
|
||||
prev_keywords = ( prev ) ? prev[ 1 ] : null;
|
||||
|
||||
// disallow overriding methods with properties
|
||||
if ( prev instanceof Function )
|
||||
{
|
||||
throw new TypeError(
|
||||
"Cannot override method '" + name + "' with property"
|
||||
this._validate.validateProperty(
|
||||
name, value, keywords, prev_data, prev_keywords
|
||||
);
|
||||
}
|
||||
|
||||
// do not allow overriding getters/setters
|
||||
if ( prev_data && ( prev_data.get || prev_data.set ) )
|
||||
{
|
||||
throw TypeError(
|
||||
"Cannot override getter/setter '" + name + "' with property"
|
||||
);
|
||||
}
|
||||
|
||||
// do not permit visibility de-escalation
|
||||
if ( prev &&
|
||||
( this._getVisibilityValue( prev[ 1 ] )
|
||||
< this._getVisibilityValue( keywords )
|
||||
)
|
||||
)
|
||||
{
|
||||
throw TypeError(
|
||||
"Cannot de-escalate visibility of property '" + name + "'"
|
||||
);
|
||||
}
|
||||
|
||||
// abstract properties do not make sense
|
||||
if ( keywords[ 'abstract' ] )
|
||||
{
|
||||
throw TypeError(
|
||||
"Property '" + name + "' cannot be declared as abstract"
|
||||
);
|
||||
}
|
||||
|
||||
if ( keywords[ 'static' ] && keywords[ 'const' ] )
|
||||
{
|
||||
throw TypeError(
|
||||
"Static keyword cannot be used with const for property '" +
|
||||
name + "'"
|
||||
);
|
||||
}
|
||||
|
||||
// properties are inherently virtual
|
||||
if ( keywords['virtual'] )
|
||||
{
|
||||
throw TypeError( "Cannot declare property '" + name + "' as virtual" );
|
||||
}
|
||||
|
||||
getMemberVisibility( members, keywords )[ name ] = [ value, keywords ];
|
||||
};
|
||||
|
|
|
@ -156,6 +156,80 @@ exports.prototype.validateMethod = function(
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Validates a property declaration, ensuring that keywords are valid, overrides
|
||||
* make sense, etc.
|
||||
*
|
||||
* Throws exception on validation failure
|
||||
*
|
||||
* @param {string} name method name
|
||||
* @param {*} value method value
|
||||
*
|
||||
* @param {Object.<string,boolean>} keywords parsed keywords
|
||||
*
|
||||
* @param {Object} prev_data data of member being overridden
|
||||
* @param {Object} prev_keywords keywords of member being overridden
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
exports.prototype.validateProperty = function(
|
||||
name, value, keywords, prev_data, prev_keywords
|
||||
)
|
||||
{
|
||||
var prev = ( prev_data ) ? prev_data.member : null;
|
||||
|
||||
// disallow overriding methods with properties
|
||||
if ( prev instanceof Function )
|
||||
{
|
||||
throw new TypeError(
|
||||
"Cannot override method '" + name + "' with property"
|
||||
);
|
||||
}
|
||||
|
||||
// do not allow overriding getters/setters
|
||||
if ( prev_data && ( prev_data.get || prev_data.set ) )
|
||||
{
|
||||
throw TypeError(
|
||||
"Cannot override getter/setter '" + name + "' with property"
|
||||
);
|
||||
}
|
||||
|
||||
// do not permit visibility de-escalation
|
||||
if ( prev &&
|
||||
( this._getVisibilityValue( prev_keywords )
|
||||
< this._getVisibilityValue( keywords )
|
||||
)
|
||||
)
|
||||
{
|
||||
throw TypeError(
|
||||
"Cannot de-escalate visibility of property '" + name + "'"
|
||||
);
|
||||
}
|
||||
|
||||
// abstract properties do not make sense
|
||||
if ( keywords[ 'abstract' ] )
|
||||
{
|
||||
throw TypeError(
|
||||
"Property '" + name + "' cannot be declared as abstract"
|
||||
);
|
||||
}
|
||||
|
||||
if ( keywords[ 'static' ] && keywords[ 'const' ] )
|
||||
{
|
||||
throw TypeError(
|
||||
"Static keyword cannot be used with const for property '" +
|
||||
name + "'"
|
||||
);
|
||||
}
|
||||
|
||||
// properties are inherently virtual
|
||||
if ( keywords['virtual'] )
|
||||
{
|
||||
throw TypeError( "Cannot declare property '" + name + "' as virtual" );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the visibility level as a numeric value, where 0 is public and 2 is
|
||||
* private
|
||||
|
|
|
@ -41,12 +41,11 @@ var common = require( './common' ),
|
|||
|
||||
mb_common.funcVal = null;
|
||||
mb_common.value = { baj: 'baz' };
|
||||
mb_common.buildMember = builder.buildProp
|
||||
|
||||
// must wrap to call in proper context
|
||||
var builder_method = function()
|
||||
var builder_method = mb_common.buildMember = function()
|
||||
{
|
||||
builder.buildMethod.apply( builder, arguments );
|
||||
builder.buildProp.apply( builder, arguments );
|
||||
}
|
||||
|
||||
// do assertions common to all member builders
|
||||
|
@ -94,6 +93,7 @@ mb_common.assertCommon();
|
|||
{
|
||||
try
|
||||
{
|
||||
mb_common.buildMember = builder_method;
|
||||
mb_common.buildMemberQuick( { 'virtual': true } );
|
||||
}
|
||||
catch ( e )
|
||||
|
|
Loading…
Reference in New Issue