1
0
Fork 0

[#25] Moved MethodBuilder property validation into MemberBuilderValidator

- Tests have not yet been moved
closure/master
Mike Gerwitz 2011-10-23 00:43:08 -04:00
parent 5e46298e39
commit a91cb01998
3 changed files with 86 additions and 57 deletions

View File

@ -51,7 +51,7 @@ module.exports = function MemberBuilder( wrap_method, wrap_override )
this._wrapOverride = wrap_override;
// XXX: temporarily tightly coupled
this._validate = validate;
this._validate = validate;
};
@ -174,58 +174,13 @@ 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;
var prev_data = scanMembers( members, name, base ),
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"
);
}
// 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" );
}
this._validate.validateProperty(
name, value, keywords, prev_data, prev_keywords
);
getMemberVisibility( members, keywords )[ name ] = [ value, keywords ];
};

View File

@ -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

View File

@ -39,14 +39,13 @@ var common = require( './common' ),
;
mb_common.funcVal = null;
mb_common.value = { baj: 'baz' };
mb_common.buildMember = builder.buildProp
mb_common.funcVal = null;
mb_common.value = { baj: 'baz' };
// 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 )