++2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
++
++ all things are for /doc support:
++
++ * doc.cs: new file that supports XML documentation generation.
++ * mcs.exe.sources: added doc.cs.
++ * driver.cs:
++ Handle /doc command line option.
++ Report error 2006 instead of 5 for missing file name for /doc.
++ Generate XML documentation when required, after type resolution.
++ * cs-tokenizer.cs:
++ Added support for picking up documentation (/// and /** ... */),
++ including a new XmlCommentState enumeration.
++ * cs-parser.jay:
++ Added lines to fill Documentation element for field, constant,
++ property, indexer, method, constructor, destructor, operator, event
++ and class, struct, interface, delegate, enum.
++ Added lines to warn incorrect comment.
++ * rootcontext.cs :
++ Added Documentation field (passed only when /doc was specified).
++ * decl.cs:
++ Added DocComment, DocCommentHeader, GenerateDocComment() and
++ OnGenerateDocComment() and some supporting private members for
++ /doc feature to MemberCore.
++ * class.cs:
++ Added GenerateDocComment() on TypeContainer, MethodCore and Operator.
++ * delegate.cs:
++ Added overriden DocCommentHeader.
++ * enum.cs:
++ Added overriden DocCommentHeader and GenerateDocComment().
++
+2004-12-01 Miguel de Icaza <miguel@ximian.com>
+
+ * cfold.cs (ConstantFold.DoConstantNumericPromotions): After
+ unwrapping the enumeration values, chain to
+ DoConstantNumericPromotions again, so we can promote things to the
+ fundamental types (takes care of enums that are bytes, sbytes).
+
+ Fixes bug #62054.
+
+2004-12-01 Raja R Harinath <rharinath@novell.com>
+
+ * attribute.cs (Attribute.CheckAttributeType): Remove complain flag.
+ Fix long-standing bug in type-lookup. Use FindType instead of
+ LookupType when ec.ResolvingTypeTree.
+ (Attribute.ResolveType, Attribute.Resolve)
+ (Attribute.DefinePInvokeMethod,GlobalAttribute.CheckAttributeType):
+ Update to changes.
+ (Attributes.Search): Remove internal version. Update.
+ (Attributes.SearchMulti): Update.
+ (Attributes.GetClsCompliantAttribute): Remove.
+ (Attributes.GetIndexerNameAttribute): Remove.
+ * decl.cs (MemberCore.GetClsCompliantAttributeValue): Update to changes.
+ (DeclSpace.GetClsCompliantAttributeValue): Likewise.
+ * class.cs (Indexer.Define): Likewise.
+
+2004-12-01 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #68790
+ * ecore.cs: CheckMarshallByRefAccess new virtual method for testing
+ MarshallByReference members access.
+
+ * expression.cs: Use CheckMarshallByRefAccess;
+ Better error CS0197 message.
+
+ * report.cs: Print whole related error message.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ * class (GetClassBases): Better error 60 report.
+ (EventProperty): Disabled warning 67 detection.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #60324
+ * cfold.cs (Assign.DoResolve): Add subtraction for DecimalConstant.
+
+ * constant.cs (DecimalConstant.Emit): Don't use int ctor for
+ precise values.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #49488
+ * assign.cs (Assign.DoResolve): Add error 1648, 1650 report.
+
+ * decl.cs (MemberCore.MemberName): Error 1648 in compiler.
+
+2004-11-26 Miguel de Icaza <miguel@ximian.com>
+
+ * attribute.cs (Attribute.Resolve): Refine error reporting and
+ report a cs0117 if the identifier does not exist, to distinguish
+ from 0617 which is a miss-use of the actual identifier.
+
+ * ecore.cs (EventExpr.Emit): Refine error report and distinguish
+ between cs0070 and cs0079.
+
+ * class.cs (MemberBase.DoDefine): When reporting a wrong
+ accessibility level, we use MethodCore to compare instead of
+ Method (this was a regression in some refactoring effort).
+
+ So now we correctly report cs0056 again.
+
+ * convert.cs (ImplicitReferenceConversion): Corrected typo, I was
+ testing the target_type (which was known to be object_type) and
+ not the source type (which is anonymous_method).
+
+ Fixed reporting of error cs1660.
+
+ * expression.cs (UserCast.Source): Expose the underlying cast.
+
+ * statement.cs (Switch.SwitchGoverningType): Sort the list of
+ allowed types to find a match to int32 first (most common).
+
+ In addition, it ignores any ImplicitUserConversions that did an
+ internal implicit conversion (as the switch statement allows only
+ one integral conversion to exist).
+
+ * class.cs (PartialContainer.Create): rename `name' to
+ `member_name' for clarity. Then replace the string calls with a
+ call to MemberName.GetPartialName, as now using
+ MemberName.ToString is an error (this is due to the side effects
+ it had, that were fixed in the past).
+
+ This will restore the error reporting on a number of partial class
+ errors that were missusing this (and getting an exception as a
+ results, which is now just a plain textual warning, because
+ yyparse debug output would crash otherwise).
+
+2004-11-26 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (PROGRAM_INSTALL_DIR): Remove.
+
+2004-11-25 Ben Maurer <bmaurer@ximian.com>
+
+ * rootcontext.cs (LookupType): Make sure to cache lookups that
+ don't give us a negative result. This saves about 5% of corlib
+ compilation time.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * report.cs (AbstractMessage.Print): messages are sent to stderr
+
+ * class.cs (TypeContainer.GetClassBases): It is an error to have a
+ non-interface in the list of interfaces (at this point, either
+ parent was properly set, or a base class is being listed in the
+ interfaces section).
+
+ This flags error 1722, and resolves the crash from bug 69259.
+
+2004-11-25 Ben Maurer <bmaurer@ximian.com>
+
+ * statement.cs (Using.EmitExpressionFinally): make this work right
+ for valuetypes. Fixes 69926.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * const.cs (Const.ChangeType): Cope with the "0 literal can be
+ converted to an enum" here, before we try to change the underlying
+ type. This code exists, but it is a different code path than the
+ one used while encoding constants.
+
+ (ImplicitReferenceConversionExists): In addition, resynchronized
+ the code here, so it matches the same code in
+ ImplicitReferenceConversionExists for the `from any class-type S
+ to any interface-type T'.
+
+2004-11-25 Marek Safar <marek.safar@seznam.cz>
+
+ * cfold.cs (BinaryFold): Add addition for DecimalConstant.
+
+2004-11-24 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Use verbosity accordingly.
+
+2004-11-24 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (Unary.ResolveOperator): Do not report warning;
+ AddressOf reads from variable.
+
+ (LocalVariableReferences.DoResolveBase): Improved my previous fix.
+
+2004-11-24 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #69462
+
+ * attribute.cs (Attributable): Removed CheckTargets.
+ (Attributes.Emit): Explicit attribute targets are tested here.
+
+ * class.cs (EventField.ValidAttributeTargets): Explicit target "field" is
+ not enabled for interfaces.
+
+ * codegen.cs (CommonAssemblyModulClass.AddAttributes): Removed CheckTargets.
+ (GetAssemblyName): Ouch next bug there.
+
+2004-11-23 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * expression.cs: Error 275 added.
+
+2004-11-23 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #69177 (Implemented decimal constant support)
+
+ * cfold.cs (DoConstantNumericPromotions: Add DecimalConstant.
+ (BinaryFold): Add DecimalConstant.
+
+ * const.cs (Define): Decimal constant
+ (is not constant.
+ (ChangeType): Add decimal type handling.
+ (LookupConstantValue): Don't set value for decimal type but
+ emit DecimalConstantAttribute. Needed for constant optimization.
+
+ * constant.cs (ToDecimal): New method.
+ (ConvertToDecimal): New method.
+ (IntConstant): Implemented ConvertToDecimal.
+ (DecimalConstant.Emit): Emit optimized version for decimals in
+ int range.
+
+ * expression.cs (ResolveOperator): Changed order of constant
+ reduction to work correctly with native types which have
+ overloaded operators.
+ (ResolveMemberAccess): Extract constant value from attribute
+ for decimal type.
+
+ * rootcontext.cs (ResolveCore): Add DecimalConstantAttribute.
+
+ * typemanager.cs (TypeManager): Add decimal_constant_attribute_type,
+ void_decimal_ctor_int_arg, decimal_constant_attribute_ctor.
+ (ChangeType): Decimal is special.
+ (TypeToCoreType): Add decimal type.
+
+2004-11-22 Marek Safar <marek.safar@seznam.cz>
+
+ * convert.cs (ImplicitConversionRequired): Add error cs0642 for
+ decimal types.
+
+2004-11-22 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (EventField.ApplyAttributeBuilder): Fix error
+ test cs1667-5.cs.
+
+2004-11-19 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MemberBase.DoDefine): Fix error cs0508 report.
+
+ * pending.cs (PendingImplementation): Grab only interfaces.
+
+2004-11-19 Marek Safar <marek.safar@seznam.cz>
+
+ * statement.cs (ForeachHelperMethods): Add location member and
+ error 202 detection.
+
+2004-11-18 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (DoResolveBase): Fixed wrong warning for out
+ variables.
+
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.TypeParameter_to_Null): Use the constraints
+ to check whether the conversion is ok.
+
+ * typemanager.cs (TypeManager.GetTypeArguments): Just return
+ `Type.EmptyTypes' if we're not a generic TypeContainer.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (ImplicitReferenceConversionExists): A surprisingly
+ old bug: when converting from the null literal to a pointer,
+ return an EmptyCast, not the NullLiteral.
+
+ This fixes #69921, the recent null_type changes probably made this
+ bug more prominent.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, call AnonymousMethod.Compatible() on it.
+
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (FieldBase): Use an unused bit field from the field to
+ encode the `has_offset' property from the FieldMember. This saves
+ a couple of Ks on bootstrap compilation.
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, return the AnonymousMethod resolved
+ expression.
+
+ * expression.cs (New.DoResolve): Allow return values from
+ NewDelegate to also include AnonymousMethods.
+
+ Fixes #70150.
+
2004-11-29 Raja R Harinath <rharinath@novell.com>
* decl.cs (MemberCore.MemberName): Remove readonly to fix an error
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
++// (C) 2004 Novell, Inc
//
//
// 2002-10-11 Miguel de Icaza <miguel@ximian.com>
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
++using System.Xml;
using Mono.CompilerServices.SymbolWriter;
}
}
++ public Constructor DefaultStaticConstructor {
++ get { return default_static_constructor; }
++ }
++
protected override bool VerifyClsCompliance (DeclSpace ds)
{
if (!base.VerifyClsCompliance (ds))
return FindMembers (mt, new_bf, null, null);
}
++ //
++ // Generates xml doc comments (if any), and if required,
++ // handle warning report.
++ //
++ internal override void GenerateDocComment (DeclSpace ds)
++ {
++ DocUtil.GenerateTypeDocComment (this, ds);
++ }
++
++ public override string DocCommentHeader {
++ get { return "T:"; }
++ }
++
public virtual MemberCache ParentCache {
get {
return parent_cache;
return false;
}
++ //
++ // Returns a string that represents the signature for this
++ // member which should be used in XML documentation.
++ //
++ public override string GetDocCommentName (DeclSpace ds)
++ {
++ return DocUtil.GetMethodDocCommentName (this, ds);
++ }
++
++ //
++ // Raised (and passed an XmlElement that contains the comment)
++ // when GenerateDocComment is writing documentation expectedly.
++ //
++ // FIXME: with a few effort, it could be done with XmlReader,
++ // that means removal of DOM use.
++ //
++ internal override void OnGenerateDocComment (DeclSpace ds, XmlElement el)
++ {
++ DocUtil.OnMethodGenerateDocComment (this, ds, el);
++ }
++
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { return "M:"; }
++ }
++
protected override void VerifyObsoleteAttribute()
{
base.VerifyObsoleteAttribute ();
base.Emit ();
}
++
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { return "F:"; }
++ }
}
//
}
}
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
++ }
++
protected override void VerifyObsoleteAttribute()
{
}
return attribute_targets;
}
}
++
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { return "P:"; }
++ }
}
public class Property : PropertyBase, IIteratorContainer {
return TypeManager.GetFullNameSignature (EventBuilder);
}
++
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { return "E:"; }
++ }
}
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
++// (C) 2004 Novell, Inc
//
// TODO:
// (1) Figure out why error productions dont work. `type-declaration' is a
/// The current file.
///
SourceFile file;
++
++ ///
++ /// Temporary Xml documentation cache.
++ /// For enum types, we need one more temporary store.
++ ///
++ string tmpComment;
++ string enumTypeComment;
++
/// Current attribute target
opt_EOF
: /* empty */
++ {
++ Lexer.check_incorrect_doc_comment ();
++ }
| EOF
++ {
++ Lexer.check_incorrect_doc_comment ();
++ }
;
outer_declarations
using_directive
: using_alias_directive
++ {
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
| using_namespace_directive
++ {
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
;
using_alias_directive
namespace_body
: OPEN_BRACE
++ {
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
opt_using_directives
opt_namespace_member_declarations
CLOSE_BRACE
} else {
$$ = new Attributes (sect);
}
++ if ($$ == null) {
++ if (RootContext.Documentation != null) {
++ Lexer.check_incorrect_doc_comment ();
++ Lexer.doc_state =
++ XmlCommentState.Allowed;
++ }
++ }
} else {
$$ = new Attributes (sect);
}
current_class.SetParameterInfo ((ArrayList) $8);
++ if (RootContext.Documentation != null)
++ current_class.DocComment = Lexer.consume_doc_comment ();
++
current_class.Register ();
}
struct_body
++ {
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
opt_semicolon
{
$$ = current_class;
;
struct_body
-- : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
++ : OPEN_BRACE
++ {
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++ opt_struct_member_declarations CLOSE_BRACE
;
opt_struct_member_declarations
(Expression) constant.expression_or_array_initializer, modflags,
(Attributes) $1, l);
++ if (RootContext.Documentation != null) {
++ c.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
current_container.AddConstant (c);
}
}
var.expression_or_array_initializer,
(Attributes) $1, l);
++ if (RootContext.Documentation != null) {
++ field.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
current_container.AddField (field);
}
}
method_declaration
: method_header {
iterator_container = (IIteratorContainer) $1;
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.NotAllowed;
}
method_body
{
current_local_parameters = null;
iterator_container = null;
++
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
}
;
current_local_parameters = (Parameters) $6;
++ if (RootContext.Documentation != null)
++ method.DocComment = Lexer.consume_doc_comment ();
++
$$ = method;
}
| opt_attributes
lexer.Location);
current_local_parameters = (Parameters) $6;
++
++ if (RootContext.Documentation != null)
++ method.DocComment = Lexer.consume_doc_comment ();
++
$$ = method;
}
| opt_attributes
lexer.Location);
current_local_parameters = (Parameters) $6;
++
++ if (RootContext.Documentation != null)
++ method.DocComment = Lexer.consume_doc_comment ();
++
$$ = method;
}
;
property_declaration
: opt_attributes
opt_modifiers
-- type namespace_or_type_name
++ type
++ namespace_or_type_name
++ {
++ if (RootContext.Documentation != null)
++ tmpComment = Lexer.consume_doc_comment ();
++ }
OPEN_BRACE
{
implicit_value_parameter_type = (Expression) $3;
CLOSE_BRACE
{
Property prop;
-- Pair pair = (Pair) $7;
++ Pair pair = (Pair) $8;
Accessor get_block = (Accessor) pair.First;
Accessor set_block = (Accessor) pair.Second;
-- Location loc = (Location) $6;
++ Location loc = (Location) $7;
MemberName name = (MemberName) $4;
if (name.TypeArguments != null)
current_container.AddProperty (prop);
implicit_value_parameter_type = null;
iterator_container = null;
++
++ if (RootContext.Documentation != null)
++ prop.DocComment = ConsumeStoredComment ();
++
}
;
$$ = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, lexer.Location);
current_local_parameters = null;
lexer.PropertyParsing = true;
++
++ if (RootContext.Documentation != null)
++ if (Lexer.doc_state == XmlCommentState.Error)
++ Lexer.doc_state = XmlCommentState.NotAllowed;
}
;
$$ = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, lexer.Location);
current_local_parameters = null;
lexer.PropertyParsing = true;
++
++ if (RootContext.Documentation != null
++ && Lexer.doc_state == XmlCommentState.Error)
++ Lexer.doc_state = XmlCommentState.NotAllowed;
}
;
current_class.SetParameterInfo ((ArrayList) $8);
++ if (RootContext.Documentation != null) {
++ current_class.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
current_class.Register ();
}
interface_body opt_semicolon
{
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++ opt_semicolon
++ {
$$ = current_class;
current_container = current_container.Parent;
Method m = (Method) $1;
current_container.AddMethod (m);
++
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_property_declaration
{
Property p = (Property) $1;
current_container.AddProperty (p);
-- }
++
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
| interface_event_declaration
{
if ($1 != null){
Event e = (Event) $1;
current_container.AddEvent (e);
}
++
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_indexer_declaration
{
Indexer i = (Indexer) $1;
current_container.AddIndexer (i);
++
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
}
;
$$ = new Method (current_class, generic, (Expression) $3, (int) $2, true, name,
(Parameters) $6, (Attributes) $1, lexer.Location);
++ if (RootContext.Documentation != null)
++ ((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new VOID namespace_or_type_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
$$ = new Method (current_class, generic, TypeManager.system_void_expr, (int) $2,
true, name, (Parameters) $6, (Attributes) $1, lexer.Location);
++ if (RootContext.Documentation != null)
++ ((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
;
$$ = new Property (current_class, (Expression) $3, (int) $2, true,
new MemberName ((string) $4), (Attributes) $1,
pinfo.Get, pinfo.Set, lexer.Location);
++ if (RootContext.Documentation != null)
++ ((Property) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes
opt_new
$$ = new EventField (current_class, (Expression) $4, (int) $2, true,
new MemberName ((string) $5), null,
(Attributes) $1, lexer.Location);
++ if (RootContext.Documentation != null)
++ ((EventField) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new EVENT type error {
CheckIdentifierToken (yyToken);
new MemberName (TypeContainer.DefaultIndexerName),
(int) $2, true, (Parameters) $6, (Attributes) $1,
info.Get, info.Set, lexer.Location);
++ if (RootContext.Documentation != null)
++ ((Indexer) $$).DocComment = ConsumeStoredComment ();
}
;
new Parameters (param_list, null, decl.location),
(ToplevelBlock) $5, (Attributes) $1, decl.location);
++ if (RootContext.Documentation != null)
++ op.DocComment = ConsumeStoredComment ();
++
if (SimpleIteratorContainer.Simple.Yields)
op.SetYields ();
op = Operator.OpType.UnaryNegation;
Parameter [] pars = new Parameter [1];
++ Expression type = (Expression) $5;
-- pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
++ pars [0] = new Parameter (type, (string) $6, Parameter.Modifier.NONE, null);
current_local_parameters = new Parameters (pars, null, lexer.Location);
-- $$ = new OperatorDeclaration (op, (Expression) $1, (Expression) $5, (string) $6,
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
++ $$ = new OperatorDeclaration (op, (Expression) $1, type, (string) $6,
null, null, lexer.Location);
}
| type OPERATOR overloadable_operator
type IDENTIFIER
CLOSE_PARENS
{
-- CheckBinaryOperator ((Operator.OpType) $3);
++ CheckBinaryOperator ((Operator.OpType) $3);
+
- Parameter [] pars = new Parameter [2];
++ Parameter [] pars = new Parameter [2];
- pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
- pars [1] = new Parameter ((Expression) $8, (string) $9, Parameter.Modifier.NONE, null);
- Parameter [] pars = new Parameter [2];
++ Expression typeL = (Expression) $5;
++ Expression typeR = (Expression) $8;
+
- pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
- pars [1] = new Parameter ((Expression) $8, (string) $9, Parameter.Modifier.NONE, null);
++ pars [0] = new Parameter (typeL, (string) $6, Parameter.Modifier.NONE, null);
++ pars [1] = new Parameter (typeR, (string) $9, Parameter.Modifier.NONE, null);
current_local_parameters = new Parameters (pars, null, lexer.Location);
++
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
$$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1,
-- (Expression) $5, (string) $6,
-- (Expression) $8, (string) $9, lexer.Location);
++ typeL, (string) $6,
++ typeR, (string) $9, lexer.Location);
}
| conversion_operator_declarator
;
c.OptAttributes = (Attributes) $1;
c.ModFlags = (int) $2;
++ if (RootContext.Documentation != null)
++ c.DocComment = ConsumeStoredComment ();
++
if (c.Name == current_container.Basename){
if ((c.ModFlags & Modifiers.STATIC) != 0){
if ((c.ModFlags & Modifiers.Accessibility) != 0){
current_container.AddConstructor (c);
current_local_parameters = null;
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
}
;
constructor_declarator
-- : IDENTIFIER
++ : IDENTIFIER
++ {
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++ }
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
oob_stack.Push (lexer.Location);
-- current_local_parameters = (Parameters) $3;
++ current_local_parameters = (Parameters) $4;
}
opt_constructor_initializer
{
Location l = (Location) oob_stack.Pop ();
-- $$ = new Constructor (current_class, (string) $1, 0, (Parameters) $3,
-- (ConstructorInitializer) $6, l);
++ $$ = new Constructor (current_class, (string) $1, 0, (Parameters) $4,
++ (ConstructorInitializer) $7, l);
}
;
;
destructor_declaration
-- : opt_attributes opt_finalizer TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
++ : opt_attributes opt_finalizer TILDE
++ {
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.NotAllowed;
++ }
++ }
++ IDENTIFIER OPEN_PARENS CLOSE_PARENS block
{
-- if ((string) $4 != current_container.Basename){
++ if ((string) $5 != current_container.Basename){
Report.Error (574, lexer.Location, "Name of destructor must match name of class");
} else if (!(current_container is Class)){
Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
Method d = new Destructor (
current_class, TypeManager.system_void_expr, m, "Finalize",
new Parameters (null, null, l), (Attributes) $1, l);
++ if (RootContext.Documentation != null)
++ d.DocComment = ConsumeStoredComment ();
-- d.Block = (ToplevelBlock) $7;
++ d.Block = (ToplevelBlock) $8;
current_container.AddMethod (d);
}
}
lexer.Location);
current_container.AddEvent (e);
--
++
++ if (RootContext.Documentation != null) {
++ e.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
}
}
| opt_attributes
current_class, (Expression) $4, (int) $2, false, name, null,
(Attributes) $1, (Accessor) pair.First, (Accessor) pair.Second,
loc);
--
++ if (RootContext.Documentation != null) {
++ e.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
current_container.AddEvent (e);
implicit_value_parameter_type = null;
}
Report.Error (71, lexer.Location, "Explicit implementation of events requires property syntax");
else
Report.Error (71, lexer.Location, "Event declaration should use property syntax");
++
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
}
;
indexer = new Indexer (current_class, decl.type, name,
(int) $2, false, decl.param_list, (Attributes) $1,
get_block, set_block, loc);
++ if (RootContext.Documentation != null)
++ indexer.DocComment = ConsumeStoredComment ();
current_container.AddIndexer (indexer);
} else if (pars.FixedParameters == null && pars.ArrayParameter == null){
Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
}
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
$$ = new IndexerDeclaration ((Expression) $1, null, pars);
}
} else if (pars.FixedParameters == null && pars.ArrayParameter == null){
Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
}
++
MemberName name = (MemberName) $2;
if (name.TypeArguments != null)
syntax_error (lexer.Location, "an indexer can't have type arguments");
$$ = new IndexerDeclaration ((Expression) $1, name, pars);
++
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
}
;
: opt_attributes
opt_modifiers
ENUM IDENTIFIER
-- opt_enum_base
++ opt_enum_base {
++ if (RootContext.Documentation != null)
++ enumTypeComment = Lexer.consume_doc_comment ();
++ }
enum_body
opt_semicolon
{
Enum e = new Enum (current_namespace, current_container, (Expression) $5, (int) $2,
full_name, (Attributes) $1, enum_location);
-- foreach (VariableDeclaration ev in (ArrayList) $6) {
++ if (RootContext.Documentation != null)
++ e.DocComment = enumTypeComment;
++
++ foreach (VariableDeclaration ev in (ArrayList) $7) {
e.AddEnumMember (ev.identifier,
(Expression) ev.expression_or_array_initializer,
-- ev.Location, ev.OptAttributes);
++ ev.Location, ev.OptAttributes,
++ ev.DocComment);
}
string name = full_name.GetName ();
;
enum_body
-- : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
++ : OPEN_BRACE
{
-- $$ = $2;
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++ opt_enum_member_declarations
++ {
++ // here will be evaluated after CLOSE_BLACE is consumed.
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++ CLOSE_BRACE
++ {
++ $$ = $3;
}
;
enum_member_declaration
: opt_attributes IDENTIFIER
{
-- $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
++ VariableDeclaration vd = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
++
++ if (RootContext.Documentation != null) {
++ vd.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
++ $$ = vd;
}
| opt_attributes IDENTIFIER
{
-- $$ = lexer.Location;
++ $$ = lexer.Location;
++ if (RootContext.Documentation != null) {
++ tmpComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.NotAllowed;
++ }
}
ASSIGN expression
{
-- $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
++ VariableDeclaration vd = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
++
++ if (RootContext.Documentation != null)
++ vd.DocComment = ConsumeStoredComment ();
++
++ $$ = vd;
}
;
Delegate del = new Delegate (current_namespace, current_container, (Expression) $4,
(int) $2, name, (Parameters) $7, (Attributes) $1, l);
++ if (RootContext.Documentation != null) {
++ del.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
current_container.AddDelegate (del);
RootContext.Tree.RecordDecl (name.GetName (true), del);
TypeManager.system_void_expr, (int) $2, name,
(Parameters) $7, (Attributes) $1, l);
++ if (RootContext.Documentation != null) {
++ del.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
current_container.AddDelegate (del);
RootContext.Tree.RecordDecl (name.GetName (true), del);
current_class.SetParameterInfo ((ArrayList) $8);
++ if (RootContext.Documentation != null) {
++ current_class.DocComment = Lexer.consume_doc_comment ();
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
++
current_class.Register ();
}
-- class_body
++ class_body
++ {
++ if (RootContext.Documentation != null)
++ Lexer.doc_state = XmlCommentState.Allowed;
++ }
opt_semicolon
{
$$ = current_class;
public object expression_or_array_initializer;
public Location Location;
public Attributes OptAttributes;
++ public string DocComment;
public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs)
{
CheckToken (1041, yyToken, "Identifier expected");
}
++string ConsumeStoredComment ()
++{
++ string s = tmpComment;
++ tmpComment = null;
++ Lexer.doc_state = XmlCommentState.Allowed;
++ return s;
++}
++
/* end end end */
}
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
++// (C) 2004 Novell, Inc
//
/*
bool handle_constraints = false;
bool handle_typeof = false;
++ //
++ // XML documentation buffer. The save point is used to divide
++ // comments on types and comments on members.
++ //
++ StringBuilder xml_comment_buffer;
++
++ //
++ // See comment on XmlCommentState enumeration.
++ //
++ XmlCommentState xmlDocState = XmlCommentState.Allowed;
++
//
// Whether tokens have been seen on this line
//
handle_typeof = value;
}
}
--
++
++ public XmlCommentState doc_state {
++ get { return xmlDocState; }
++ set {
++ if (value == XmlCommentState.Allowed) {
++ check_incorrect_doc_comment ();
++ consume_doc_comment ();
++ }
++ xmlDocState = value;
++ }
++ }
++
//
// Class variables
//
define (def);
}
++ xml_comment_buffer = new StringBuilder ();
++
//
// FIXME: This could be `Location.Push' but we have to
// find out why the MS compiler allows this
case '}':
return Token.CLOSE_BRACE;
case '[':
++ // To block doccomment inside attribute declaration.
++ if (doc_state == XmlCommentState.Allowed)
++ doc_state = XmlCommentState.NotAllowed;
return Token.OPEN_BRACKET;
case ']':
return Token.CLOSE_BRACKET;
{
int res = consume_identifier (s, false);
++ if (doc_state == XmlCommentState.Allowed)
++ doc_state = XmlCommentState.NotAllowed;
++ switch (res) {
++ case Token.USING:
++ case Token.NAMESPACE:
++ check_incorrect_doc_comment ();
++ break;
++ }
++
if (res == Token.PARTIAL) {
// Save current position and parse next token.
int old = reader.Position;
if (d == '/'){
getChar ();
++ if (RootContext.Documentation != null && peekChar () == '/') {
++ getChar ();
++ // Allow only ///ws.
++ // Don't allow ////.
++ if ((d = peekChar ()) == ' ' || d == '\t') {
++ if (doc_state == XmlCommentState.Allowed)
++ handle_one_line_xml_comment ();
++ else if (doc_state == XmlCommentState.NotAllowed)
++ warn_incorrect_doc_comment ();
++ }
++ }
while ((d = getChar ()) != -1 && (d != '\n') && d != '\r')
col++;
if (d == '\n'){
continue;
} else if (d == '*'){
getChar ();
++ bool docAppend = false;
++ if (RootContext.Documentation != null && peekChar () == '*') {
++ getChar ();
++ // But when it is /**/, just do nothing.
++ if (peekChar () == '/') {
++ getChar ();
++ continue;
++ }
++ if (doc_state == XmlCommentState.Allowed)
++ docAppend = true;
++ else if (doc_state == XmlCommentState.NotAllowed)
++ warn_incorrect_doc_comment ();
++ }
++
++ int currentCommentStart = 0;
++ if (docAppend) {
++ currentCommentStart = xml_comment_buffer.Length;
++ xml_comment_buffer.Append (Environment.NewLine);
++ }
while ((d = getChar ()) != -1){
if (d == '*' && peekChar () == '/'){
col++;
break;
}
++ if (docAppend)
++ xml_comment_buffer.Append ((char) d);
++
if (d == '\n'){
line++;
ref_line++;
tokens_seen = false;
}
}
++ if (docAppend)
++ update_formatted_doc_comment (currentCommentStart);
continue;
}
goto is_punct_label;
return Token.ERROR;
}
++ //
++ // Handles one line xml comment
++ //
++ private void handle_one_line_xml_comment ()
++ {
++ int c;
++ while ((c = peekChar ()) == ' ')
++ getChar (); // skip heading whitespaces.
++ while ((c = peekChar ()) != -1 && c != '\n' && c != '\r') {
++ col++;
++ xml_comment_buffer.Append ((char) getChar ());
++ }
++ if (c == '\r' || c == '\n')
++ xml_comment_buffer.Append (Environment.NewLine);
++ }
++
++ //
++ // Remove heading "*" in Javadoc-like xml documentation.
++ //
++ private void update_formatted_doc_comment (int currentCommentStart)
++ {
++ int length = xml_comment_buffer.Length - currentCommentStart;
++ string [] lines = xml_comment_buffer.ToString (
++ currentCommentStart,
++ length).Replace ("\r", "").Split ('\n');
++ // The first line starts with /**, thus it is not target
++ // for the format check.
++ for (int i = 1; i < lines.Length; i++) {
++ string s = lines [i];
++ int idx = s.IndexOf ('*');
++ string head = null;
++ if (idx < 0) {
++ if (i < lines.Length - 1)
++ return;
++ head = s;
++ }
++ else
++ head = s.Substring (0, idx);
++ foreach (char c in head)
++ if (c != ' ')
++ return;
++ lines [i] = s.Substring (idx + 1);
++ }
++ xml_comment_buffer.Remove (currentCommentStart, length);
++ xml_comment_buffer.Insert (
++ currentCommentStart,
++ String.Join (Environment.NewLine, lines));
++ }
++
++ //
++ // Checks if there was incorrect doc comments and raise
++ // warnings.
++ //
++ public void check_incorrect_doc_comment ()
++ {
++ if (xml_comment_buffer.Length > 0)
++ warn_incorrect_doc_comment ();
++ }
++
++ //
++ // Raises a warning when tokenizer found incorrect doccomment
++ // markup.
++ //
++ private void warn_incorrect_doc_comment ()
++ {
++ doc_state = XmlCommentState.Error;
++ // in csc, it is 'XML comment is not placed on a valid
++ // language element'. But that does not make sense.
++ Report.Warning (1587, 2, Location, "XML comment is placed on an invalid language element which can not accept it.");
++ }
++
++ //
++ // Consumes the saved xml comment lines (if any)
++ // as for current target member or type.
++ //
++ public string consume_doc_comment ()
++ {
++ if (xml_comment_buffer.Length > 0) {
++ string ret = xml_comment_buffer.ToString ();
++ xml_comment_buffer.Length = 0;
++ return ret;
++ }
++ return null;
++ }
++
public void cleanup ()
{
if (ifstack != null && ifstack.Count >= 1) {
}
}
++
++ //
++ // Indicates whether it accepts XML documentation or not.
++ //
++ public enum XmlCommentState {
++ // comment is allowed in this state.
++ Allowed,
++ // comment is not allowed in this state.
++ NotAllowed,
++ // once comments appeared when it is NotAllowed, then the
++ // state is changed to it, until the state is changed to
++ // .Allowed.
++ Error
++ }
}
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
++// (C) 2004 Novell, Inc
//
// TODO: Move the method verification stuff from the class.cs and interface.cs here
//
using System.Globalization;
using System.Reflection.Emit;
using System.Reflection;
++using System.Xml;
namespace Mono.CSharp {
/// </summary>
public readonly Location Location;
++ /// <summary>
++ /// XML documentation comment
++ /// </summary>
++ public string DocComment;
++
++ /// <summary>
++ /// Represents header string for documentation comment
++ /// for each member types.
++ /// </summary>
++ public abstract string DocCommentHeader { get; }
++
[Flags]
public enum Flags {
Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet
/// <summary>
/// Returns true when MemberCore is exposed from assembly.
/// </summary>
-- protected bool IsExposedFromAssembly (DeclSpace ds)
++ public bool IsExposedFromAssembly (DeclSpace ds)
{
if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
return false;
protected abstract void VerifyObsoleteAttribute ();
++ //
++ // Raised (and passed an XmlElement that contains the comment)
++ // when GenerateDocComment is writing documentation expectedly.
++ //
++ internal virtual void OnGenerateDocComment (DeclSpace ds, XmlElement intermediateNode)
++ {
++ }
++
++ //
++ // Returns a string that represents the signature for this
++ // member which should be used in XML documentation.
++ //
++ public virtual string GetDocCommentName (DeclSpace ds)
++ {
++ if (ds == null || this is DeclSpace)
++ return DocCommentHeader + Name;
++ else
++ return String.Concat (DocCommentHeader, ds.Name, ".", Name);
++ }
++
++ //
++ // Generates xml doc comments (if any), and if required,
++ // handle warning report.
++ //
++ internal virtual void GenerateDocComment (DeclSpace ds)
++ {
++ DocUtil.GenerateDocComment (this, ds);
++ }
}
/// <summary>
IDictionaryEnumerator it = parent.member_hash.GetEnumerator ();
while (it.MoveNext ()) {
hash [it.Key] = ((ArrayList) it.Value).Clone ();
-- }
++ }
return hash;
}
}
}
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { return "T:"; }
++ }
++
protected override void VerifyObsoleteAttribute()
{
CheckUsageOfObsoleteAttribute (ret_type);
--- /dev/null
--- /dev/null
++//
++// doc.cs: Support for XML documentation comment.
++//
++// Author:
++// Atsushi Enomoto <atsushi@ximian.com>
++//
++// Licensed under the terms of the GNU GPL
++//
++// (C) 2004 Novell, Inc.
++//
++//
++using System;
++using System.Collections;
++using System.Collections.Specialized;
++using System.IO;
++using System.Reflection;
++using System.Reflection.Emit;
++using System.Runtime.CompilerServices;
++using System.Runtime.InteropServices;
++using System.Security;
++using System.Security.Permissions;
++using System.Text;
++using System.Xml;
++
++using Mono.CompilerServices.SymbolWriter;
++
++namespace Mono.CSharp {
++
++ //
++ // Support class for XML documentation.
++ //
++ public class DocUtil
++ {
++ // TypeContainer
++
++ //
++ // Generates xml doc comments (if any), and if required,
++ // handle warning report.
++ //
++ internal static void GenerateTypeDocComment (TypeContainer t,
++ DeclSpace ds)
++ {
++ GenerateDocComment (t, ds);
++
++ if (t.DefaultStaticConstructor != null)
++ t.DefaultStaticConstructor.GenerateDocComment (t);
++
++ if (t.InstanceConstructors != null)
++ foreach (Constructor c in t.InstanceConstructors)
++ c.GenerateDocComment (t);
++
++ if (t.Types != null)
++ foreach (TypeContainer tc in t.Types)
++ tc.GenerateDocComment (t);
++
++ if (t.Parts != null) {
++ IDictionary comments = RootContext.Documentation.PartialComments;
++ foreach (ClassPart cp in t.Parts) {
++ if (cp.DocComment == null)
++ continue;
++ comments [cp] = cp;
++ }
++ }
++
++ if (t.Enums != null)
++ foreach (Enum en in t.Enums)
++ en.GenerateDocComment (t);
++
++ if (t.Constants != null)
++ foreach (Const c in t.Constants)
++ c.GenerateDocComment (t);
++
++ if (t.Fields != null)
++ foreach (Field f in t.Fields)
++ f.GenerateDocComment (t);
++
++ if (t.Events != null)
++ foreach (Event e in t.Events)
++ e.GenerateDocComment (t);
++
++ if (t.Indexers != null)
++ foreach (Indexer ix in t.Indexers)
++ ix.GenerateDocComment (t);
++
++ if (t.Properties != null)
++ foreach (Property p in t.Properties)
++ p.GenerateDocComment (t);
++
++ if (t.Methods != null)
++ foreach (Method m in t.Methods)
++ m.GenerateDocComment (t);
++
++ if (t.Operators != null)
++ foreach (Operator o in t.Operators)
++ o.GenerateDocComment (t);
++ }
++
++ // MemberCore
++ private static readonly string lineHead =
++ Environment.NewLine + " ";
++
++ private static XmlNode GetDocCommentNode (MemberCore mc,
++ string name)
++ {
++ // FIXME: It could be even optimizable as not
++ // to use XmlDocument. But anyways the nodes
++ // are not kept in memory.
++ XmlDocument doc = RootContext.Documentation.XmlDocumentation;
++ try {
++ XmlElement el = doc.CreateElement ("member");
++ el.SetAttribute ("name", name);
++ string normalized = mc.DocComment;
++ el.InnerXml = normalized;
++ // csc keeps lines as written in the sources
++ // and inserts formatting indentation (which
++ // is different from XmlTextWriter.Formatting
++ // one), but when a start tag contains an
++ // endline, it joins the next line. We don't
++ // have to follow such a hacky behavior.
++ string [] split =
++ normalized.Split ('\n');
++ int j = 0;
++ for (int i = 0; i < split.Length; i++) {
++ string s = split [i].TrimEnd ();
++ if (s.Length > 0)
++ split [j++] = s;
++ }
++ el.InnerXml = lineHead + String.Join (
++ lineHead, split, 0, j);
++ return el;
++ } catch (XmlException ex) {
++ Report.Warning (1570, 1, mc.Location, "XML comment on '{0}' has non-well-formed XML ({1}).", name, ex.Message);
++ XmlComment com = doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name));
++ return com;
++ }
++ }
++
++ //
++ // Generates xml doc comments (if any), and if required,
++ // handle warning report.
++ //
++ internal static void GenerateDocComment (MemberCore mc,
++ DeclSpace ds)
++ {
++ if (mc.DocComment != null) {
++ string name = mc.GetDocCommentName (ds);
++
++ XmlNode n = GetDocCommentNode (mc, name);
++
++ XmlElement el = n as XmlElement;
++ if (el != null) {
++ mc.OnGenerateDocComment (ds, el);
++
++ // FIXME: it could be done with XmlReader
++ foreach (XmlElement inc in n.SelectNodes (".//include"))
++ HandleInclude (mc, inc);
++
++ // FIXME: it could be done with XmlReader
++ DeclSpace dsTarget = mc as DeclSpace;
++ if (dsTarget == null)
++ dsTarget = ds;
++
++ foreach (XmlElement see in n.SelectNodes (".//see"))
++ HandleSee (mc, dsTarget, see);
++ foreach (XmlElement seealso in n.SelectNodes (".//seealso"))
++ HandleSeeAlso (mc, dsTarget, seealso);
++ foreach (XmlElement see in n.SelectNodes (".//exception"))
++ HandleException (mc, dsTarget, see);
++ }
++
++ n.WriteTo (RootContext.Documentation.XmlCommentOutput);
++ }
++ else if (mc.IsExposedFromAssembly (ds) &&
++ // There are no warnings when the container also
++ // misses documentations.
++ (ds == null || ds.DocComment != null))
++ {
++ Report.Warning (1591, 4, mc.Location,
++ "Missing XML comment for publicly visible type or member '{0}'", mc.GetSignatureForError ());
++ }
++ }
++
++ //
++ // Processes "include" element. Check included file and
++ // embed the document content inside this documentation node.
++ //
++ private static void HandleInclude (MemberCore mc, XmlElement el)
++ {
++ string file = el.GetAttribute ("file");
++ string path = el.GetAttribute ("path");
++ if (file == "") {
++ Report.Warning (1590, 1, mc.Location, "Invalid XML 'include' element; Missing 'file' attribute.");
++ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
++ }
++ else if (path == "") {
++ Report.Warning (1590, 1, mc.Location, "Invalid XML 'include' element; Missing 'path' attribute.");
++ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
++ }
++ else {
++ XmlDocument doc = RootContext.Documentation.StoredDocuments [file] as XmlDocument;
++ if (doc == null) {
++ try {
++ doc = new XmlDocument ();
++ doc.Load (file);
++ RootContext.Documentation.StoredDocuments.Add (file, doc);
++ } catch (Exception) {
++ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file '{0}': cannot be included ", file)), el);
++ Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- '{0}'", file);
++ }
++ }
++ bool keepIncludeNode = false;
++ if (doc != null) {
++ try {
++ XmlNodeList nl = doc.SelectNodes (path);
++ if (nl.Count == 0) {
++ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el);
++
++ keepIncludeNode = true;
++ }
++ foreach (XmlNode n in nl)
++ el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el);
++ } catch (Exception ex) {
++ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Failed to insert some or all of included XML "), el);
++ Report.Warning (1589, 1, mc.Location, "Unable to include XML fragment '{0}' of file {1} -- {2}.", path, file, ex.Message);
++ }
++ }
++ if (!keepIncludeNode)
++ el.ParentNode.RemoveChild (el);
++ }
++ }
++
++ //
++ // Handles <see> elements.
++ //
++ private static void HandleSee (MemberCore mc,
++ DeclSpace ds, XmlElement see)
++ {
++ HandleXrefCommon (mc, ds, see);
++ }
++
++ //
++ // Handles <seealso> elements.
++ //
++ private static void HandleSeeAlso (MemberCore mc,
++ DeclSpace ds, XmlElement seealso)
++ {
++ HandleXrefCommon (mc, ds, seealso);
++ }
++
++ //
++ // Handles <exception> elements.
++ //
++ private static void HandleException (MemberCore mc,
++ DeclSpace ds, XmlElement seealso)
++ {
++ HandleXrefCommon (mc, ds, seealso);
++ }
++
++ static readonly char [] wsChars =
++ new char [] {' ', '\t', '\n', '\r'};
++
++ //
++ // returns a full runtime type name from a name which might
++ // be C# specific type name.
++ //
++ private static Type FindDocumentedType (MemberCore mc,
++ string name, DeclSpace ds, bool allowAlias)
++ {
++ bool isArray = false;
++ string identifier = name;
++ if (name [name.Length - 1] == ']') {
++ string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
++ if (tmp [tmp.Length - 1] == '[') {
++ identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
++ isArray = true;
++ }
++ }
++ Type t = FindDocumentedTypeNonArray (mc, identifier,
++ ds, allowAlias);
++ if (t != null && isArray)
++ t = Array.CreateInstance (t, 0).GetType ();
++ return t;
++ }
++
++ private static Type FindDocumentedTypeNonArray (MemberCore mc,
++ string identifier, DeclSpace ds, bool allowAlias)
++ {
++ switch (identifier) {
++ case "int":
++ return typeof (int);
++ case "uint":
++ return typeof (uint);
++ case "short":
++ return typeof (short);
++ case "ushort":
++ return typeof (ushort);
++ case "long":
++ return typeof (long);
++ case "ulong":
++ return typeof (ulong);
++ case "float":
++ return typeof (float);
++ case "double":
++ return typeof (double);
++ case "char":
++ return typeof (char);
++ case "decimal":
++ return typeof (decimal);
++ case "byte":
++ return typeof (byte);
++ case "sbyte":
++ return typeof (sbyte);
++ case "object":
++ return typeof (object);
++ case "bool":
++ return typeof (bool);
++ case "string":
++ return typeof (string);
++ case "void":
++ return typeof (void);
++ }
++ if (allowAlias) {
++ string alias = ds.LookupAlias (identifier);
++ if (alias != null)
++ identifier = alias;
++ }
++ Type t = ds.FindType (mc.Location, identifier);
++ if (t == null)
++ t = TypeManager.LookupTypeDirect (identifier);
++ return t;
++ }
++
++ //
++ // Returns a MemberInfo that is referenced in XML documentation
++ // (by "see" or "seealso" elements).
++ //
++ private static MemberInfo FindDocumentedMember (MemberCore mc,
++ Type type, string memberName, Type [] paramList,
++ DeclSpace ds, out int warningType, string cref)
++ {
++ warningType = 0;
++ MethodSignature msig = new MethodSignature (memberName, null, paramList);
++ MemberInfo [] mis = type.FindMembers (
++ MemberTypes.All,
++ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
++ MethodSignature.method_signature_filter,
++ msig);
++ if (mis.Length > 0)
++ return mis [0];
++
++ if (paramList.Length == 0) {
++ // search for fields/events etc.
++ mis = type.FindMembers (
++ MemberTypes.All,
++ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
++ Type.FilterName,
++ memberName);
++ return (mis.Length > 0) ? mis [0] : null;
++ }
++
++ // search for operators (whose parameters exactly
++ // matches with the list) and possibly report CS1581.
++ string oper = null;
++ string returnTypeName = null;
++ if (memberName.StartsWith ("implicit operator ")) {
++ oper = "op_Implicit";
++ returnTypeName = memberName.Substring (18).Trim (wsChars);
++ }
++ else if (memberName.StartsWith ("explicit operator ")) {
++ oper = "op_Explicit";
++ returnTypeName = memberName.Substring (18).Trim (wsChars);
++ }
++ else if (memberName.StartsWith ("operator ")) {
++ oper = memberName.Substring (9).Trim (wsChars);
++ switch (oper) {
++ // either unary or binary
++ case "+":
++ oper = paramList.Length == 2 ?
++ Binary.oper_names [(int) Binary.Operator.Addition] :
++ Unary.oper_names [(int) Unary.Operator.UnaryPlus];
++ break;
++ case "-":
++ oper = paramList.Length == 2 ?
++ Binary.oper_names [(int) Binary.Operator.Subtraction] :
++ Unary.oper_names [(int) Unary.Operator.UnaryNegation];
++ break;
++ // unary
++ case "!":
++ oper = Unary.oper_names [(int) Unary.Operator.LogicalNot]; break;
++ case "~":
++ oper = Unary.oper_names [(int) Unary.Operator.OnesComplement]; break;
++
++ case "++":
++ oper = "op_Increment"; break;
++ case "--":
++ oper = "op_Decrement"; break;
++ case "true":
++ oper = "op_True"; break;
++ case "false":
++ oper = "op_False"; break;
++ // binary
++ case "*":
++ oper = Binary.oper_names [(int) Binary.Operator.Multiply]; break;
++ case "/":
++ oper = Binary.oper_names [(int) Binary.Operator.Division]; break;
++ case "%":
++ oper = Binary.oper_names [(int) Binary.Operator.Modulus]; break;
++ case "&":
++ oper = Binary.oper_names [(int) Binary.Operator.BitwiseAnd]; break;
++ case "|":
++ oper = Binary.oper_names [(int) Binary.Operator.BitwiseOr]; break;
++ case "^":
++ oper = Binary.oper_names [(int) Binary.Operator.ExclusiveOr]; break;
++ case "<<":
++ oper = Binary.oper_names [(int) Binary.Operator.LeftShift]; break;
++ case ">>":
++ oper = Binary.oper_names [(int) Binary.Operator.RightShift]; break;
++ case "==":
++ oper = Binary.oper_names [(int) Binary.Operator.Equality]; break;
++ case "!=":
++ oper = Binary.oper_names [(int) Binary.Operator.Inequality]; break;
++ case "<":
++ oper = Binary.oper_names [(int) Binary.Operator.LessThan]; break;
++ case ">":
++ oper = Binary.oper_names [(int) Binary.Operator.GreaterThan]; break;
++ case "<=":
++ oper = Binary.oper_names [(int) Binary.Operator.LessThanOrEqual]; break;
++ case ">=":
++ oper = Binary.oper_names [(int) Binary.Operator.GreaterThanOrEqual]; break;
++ default:
++ warningType = 1584;
++ Report.Warning (1020, 1, mc.Location, "Overloadable {0} operator is expected", paramList.Length == 2 ? "binary" : "unary");
++ Report.Warning (1584, 1, mc.Location, "XML comment on '{0}' has syntactically incorrect attribute '{1}'", mc.GetSignatureForError (), cref);
++ return null;
++ }
++ }
++ // here we still does not consider return type (to
++ // detect CS1581 or CS1002+CS1584).
++ msig = new MethodSignature (oper, null, paramList);
++ mis = type.FindMembers (
++ MemberTypes.Method,
++ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static,
++ MethodSignature.method_signature_filter,
++ msig);
++ if (mis.Length == 0)
++ return null; // CS1574
++ MemberInfo mi = mis [0];
++ Type expected = mi is MethodInfo ?
++ ((MethodInfo) mi).ReturnType :
++ mi is PropertyInfo ?
++ ((PropertyInfo) mi).PropertyType :
++ null;
++ if (returnTypeName != null) {
++ Type returnType = FindDocumentedType (mc, returnTypeName, ds, true);
++ if (returnType == null || returnType != expected) {
++ warningType = 1581;
++ Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute '{0}'", cref);
++ return null;
++ }
++ }
++ return mis [0];
++ }
++
++ private static Type [] emptyParamList = new Type [0];
++
++ //
++ // Processes "see" or "seealso" elements.
++ // Checks cref attribute.
++ //
++ private static void HandleXrefCommon (MemberCore mc,
++ DeclSpace ds, XmlElement xref)
++ {
++ string cref = xref.GetAttribute ("cref").Trim (wsChars);
++ // when, XmlReader, "if (cref == null)"
++ if (!xref.HasAttribute ("cref"))
++ return;
++ if (cref.Length == 0)
++ Report.Warning (1001, 1, mc.Location, "Identifier expected");
++ // ... and continue until CS1584.
++
++ string signature; // "x:" are stripped
++ string name; // method invokation "(...)" are removed
++ string identifiers; // array indexer "[]" are removed
++ string parameters; // method parameter list
++
++ // strip 'T:' 'M:' 'F:' 'P:' 'E:' etc.
++ // Here, MS ignores its member kind. No idea why.
++ if (cref.Length > 2 && cref [1] == ':')
++ signature = cref.Substring (2).Trim (wsChars);
++ else
++ signature = cref;
++
++ int parensPos = signature.IndexOf ('(');
++ if (parensPos > 0 && signature [signature.Length - 1] == ')') {
++ name = signature.Substring (0, parensPos).Trim (wsChars);
++ parameters = signature.Substring (parensPos + 1, signature.Length - parensPos - 2);
++ }
++ else {
++ name = signature;
++ parameters = String.Empty;
++ }
++
++ string identifier = name;
++
++ if (name.Length > 0 && name [name.Length - 1] == ']') {
++ string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
++ if (tmp [tmp.Length - 1] == '[')
++ identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
++ }
++
++ // Check if identifier is valid.
++ // This check is not necessary to mark as error, but
++ // csc specially reports CS1584 for wrong identifiers.
++ foreach (string nameElem in identifier.Split ('.')) {
++ if (!Tokenizer.IsValidIdentifier (nameElem)
++ && nameElem.IndexOf ("operator") < 0) {
++ if (nameElem.EndsWith ("[]") &&
++ Tokenizer.IsValidIdentifier (
++ nameElem.Substring (
++ 0, nameElem.Length - 2)))
++ continue;
++
++ Report.Warning (1584, 1, mc.Location, "XML comment on '{0}' has syntactically incorrect attribute '{1}'", mc.GetSignatureForError (), cref);
++ xref.SetAttribute ("cref", "!:" + signature);
++ return;
++ }
++ }
++
++ // check if parameters are valid
++ Type [] parameterTypes = emptyParamList;
++ if (parameters.Length > 0) {
++ string [] paramList = parameters.Split (',');
++ ArrayList plist = new ArrayList ();
++ for (int i = 0; i < paramList.Length; i++) {
++ string paramTypeName = paramList [i].Trim (wsChars);
++ Type paramType = FindDocumentedType (mc, paramTypeName, ds, true);
++ if (paramType == null) {
++ Report.Warning (1580, 1, mc.Location, "Invalid type for parameter '{0}' in XML comment cref attribute '{1}'", i + 1, cref);
++ return;
++ }
++ plist.Add (paramType);
++ }
++ parameterTypes = plist.ToArray (typeof (Type)) as Type [];
++ StringBuilder sb = new StringBuilder ();
++ sb.Append ('(');
++ for (int i = 0; i < parameterTypes.Length; i++) {
++ Type t = parameterTypes [i];
++ if (sb.Length > 1)
++ sb.Append (',');
++ sb.Append (t.FullName.Replace ('+', '.'));
++ }
++ sb.Append (')');
++ parameters = sb.ToString ();
++ }
++
++ Type type = FindDocumentedType (mc, name, ds, true);
++ if (type != null) {
++ xref.SetAttribute ("cref", "T:" + type.FullName.Replace ("+", "."));
++ return; // a type
++ }
++
++ // don't use identifier here. System[] is not alloed.
++ if (Namespace.IsNamespace (name)) {
++ xref.SetAttribute ("cref", "N:" + name);
++ return; // a namespace
++ }
++
++ int period = name.LastIndexOf ('.');
++ if (period > 0) {
++ string typeName = name.Substring (0, period);
++ string memberName = name.Substring (period + 1);
++ type = FindDocumentedType (mc, typeName, ds, false);
++ int warnResult;
++ if (type != null) {
++ MemberInfo mi = FindDocumentedMember (mc, type, memberName, parameterTypes, ds, out warnResult, cref);
++ if (warnResult > 0)
++ return;
++ if (mi != null) {
++ xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + type.FullName.Replace ("+", ".") + "." + memberName + parameters);
++ return; // a member of a type
++ }
++ }
++ }
++ else {
++ int warnResult;
++ MemberInfo mi = FindDocumentedMember (mc, ds.TypeBuilder, name, parameterTypes, ds, out warnResult, cref);
++ if (warnResult > 0)
++ return;
++ if (mi != null) {
++ xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + ds.TypeBuilder.FullName.Replace ("+", ".") + "." + name);
++ return; // local member name
++ }
++ }
++
++ Report.Warning (1574, 1, mc.Location, "XML comment on '{0}' has cref attribute '{1}' that could not be resolved in '{2}'.", mc.GetSignatureForError (), cref, ds.GetSignatureForError ());
++
++ xref.SetAttribute ("cref", "!:" + name);
++ }
++
++ //
++ // Get a prefix from member type for XML documentation (used
++ // to formalize cref target name).
++ //
++ static string GetMemberDocHead (MemberTypes type)
++ {
++ switch (type) {
++ case MemberTypes.Constructor:
++ case MemberTypes.Method:
++ return "M:";
++ case MemberTypes.Event:
++ return "E:";
++ case MemberTypes.Field:
++ return "F:";
++ case MemberTypes.NestedType:
++ case MemberTypes.TypeInfo:
++ return "T:";
++ case MemberTypes.Property:
++ return "P:";
++ }
++ return "!:";
++ }
++
++ // MethodCore
++
++ //
++ // Returns a string that represents the signature for this
++ // member which should be used in XML documentation.
++ //
++ public static string GetMethodDocCommentName (MethodCore mc, DeclSpace ds)
++ {
++ Parameter [] plist = mc.Parameters.FixedParameters;
++ Parameter parr = mc.Parameters.ArrayParameter;
++ string paramSpec = String.Empty;
++ if (plist != null) {
++ StringBuilder psb = new StringBuilder ();
++ foreach (Parameter p in plist) {
++ psb.Append (psb.Length != 0 ? "," : "(");
++ psb.Append (p.ParameterType.FullName.Replace ("+", "."));
++ }
++ paramSpec = psb.ToString ();
++ }
++ if (parr != null)
++ paramSpec += String.Concat (
++ paramSpec == String.Empty ? "(" : ",",
++ parr.ParameterType.FullName.Replace ("+", "."));
++
++ if (paramSpec.Length > 0)
++ paramSpec += ")";
++
++ string name = mc is Constructor ? "#ctor" : mc.Name;
++ return String.Concat (mc.DocCommentHeader, ds.Name, ".", name, paramSpec);
++ }
++
++ //
++ // Raised (and passed an XmlElement that contains the comment)
++ // when GenerateDocComment is writing documentation expectedly.
++ //
++ // FIXME: with a few effort, it could be done with XmlReader,
++ // that means removal of DOM use.
++ //
++ internal static void OnMethodGenerateDocComment (
++ MethodCore mc, DeclSpace ds, XmlElement el)
++ {
++ Hashtable paramTags = new Hashtable ();
++ foreach (XmlElement pelem in el.SelectNodes ("param")) {
++ int i;
++ string xname = pelem.GetAttribute ("name");
++ if (xname == "")
++ continue; // really? but MS looks doing so
++ if (xname != "" && mc.Parameters.GetParameterByName (xname, out i) == null)
++ Report.Warning (1572, 2, mc.Location, "XML comment on '{0}' has a 'param' tag for '{1}', but there is no such parameter.", mc.Name, xname);
++ else if (paramTags [xname] != null)
++ Report.Warning (1571, 2, mc.Location, "XML comment on '{0}' has a duplicate param tag for '{1}'", mc.Name, xname);
++ paramTags [xname] = xname;
++ }
++ Parameter [] plist = mc.Parameters.FixedParameters;
++ Parameter parr = mc.Parameters.ArrayParameter;
++ if (plist != null) {
++ foreach (Parameter p in plist) {
++ if (paramTags.Count > 0 && paramTags [p.Name] == null)
++ Report.Warning (1573, 4, mc.Location, "Parameter '{0}' has no matching param tag in the XML comment for '{1}' (but other parameters do)", mc.Name, p.Name);
++ }
++ }
++ }
++
++ // Enum
++ public static void GenerateEnumDocComment (Enum e, DeclSpace ds)
++ {
++ GenerateDocComment (e, ds);
++ foreach (string name in e.ordered_enums) {
++ MemberCore mc = e.GetDefinition (name);
++ GenerateDocComment (mc, e);
++ }
++ }
++ }
++
++ //
++ // Implements XML documentation generation.
++ //
++ public class Documentation
++ {
++ public Documentation (string xml_output_filename)
++ {
++ docfilename = xml_output_filename;
++ XmlDocumentation = new XmlDocument ();
++ XmlDocumentation.PreserveWhitespace = false;
++ }
++
++ private string docfilename;
++
++ //
++ // Used to create element which helps well-formedness checking.
++ //
++ public XmlDocument XmlDocumentation;
++
++ //
++ // The output for XML documentation.
++ //
++ public XmlWriter XmlCommentOutput;
++
++ //
++ // Stores XmlDocuments that are included in XML documentation.
++ // Keys are included filenames, values are XmlDocuments.
++ //
++ public Hashtable StoredDocuments = new Hashtable ();
++
++ //
++ // Stores comments on partial types (should handle uniquely).
++ // Keys are PartialContainers, values are comment strings
++ // (didn't use StringBuilder; usually we have just 2 or more).
++ //
++ public IDictionary PartialComments = new ListDictionary ();
++
++ //
++ // Outputs XML documentation comment from tokenized comments.
++ //
++ public bool OutputDocComment (string asmfilename)
++ {
++ XmlTextWriter w = null;
++ try {
++ w = new XmlTextWriter (docfilename, null);
++ w.Indentation = 4;
++ w.Formatting = Formatting.Indented;
++ w.WriteStartDocument ();
++ w.WriteStartElement ("doc");
++ w.WriteStartElement ("assembly");
++ w.WriteStartElement ("name");
++ w.WriteString (Path.ChangeExtension (asmfilename, null));
++ w.WriteEndElement (); // name
++ w.WriteEndElement (); // assembly
++ w.WriteStartElement ("members");
++ XmlCommentOutput = w;
++ GenerateDocComment ();
++ w.WriteFullEndElement (); // members
++ w.WriteEndElement ();
++ w.WriteWhitespace (Environment.NewLine);
++ w.WriteEndDocument ();
++ return true;
++ } catch (Exception ex) {
++ Report.Error (1569, "Error generating XML documentation file '{0}' ('{1}')", docfilename, ex.Message);
++ return false;
++ } finally {
++ if (w != null)
++ w.Close ();
++ }
++ }
++
++ //
++ // Fixes full type name of each documented types/members up.
++ //
++ public void GenerateDocComment ()
++ {
++ TypeContainer root = RootContext.Tree.Types;
++ if (root.Interfaces != null)
++ foreach (Interface i in root.Interfaces)
++ DocUtil.GenerateTypeDocComment (i, null);
++
++ if (root.Types != null)
++ foreach (TypeContainer tc in root.Types)
++ DocUtil.GenerateTypeDocComment (tc, null);
++
++ if (root.Parts != null) {
++ IDictionary comments = PartialComments;
++ foreach (ClassPart cp in root.Parts) {
++ if (cp.DocComment == null)
++ continue;
++ comments [cp] = cp;
++ }
++ }
++
++ if (root.Delegates != null)
++ foreach (Delegate d in root.Delegates)
++ DocUtil.GenerateDocComment (d, null);
++
++ if (root.Enums != null)
++ foreach (Enum e in root.Enums)
++ DocUtil.GenerateEnumDocComment (e, null);
++
++ IDictionary table = new ListDictionary ();
++ foreach (ClassPart cp in PartialComments.Keys) {
++ table [cp.PartialContainer] += cp.DocComment;
++ }
++ foreach (PartialContainer pc in table.Keys) {
++ pc.DocComment = table [pc] as string;
++ DocUtil.GenerateDocComment (pc, null);
++ }
++ }
++ }
++}
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
++// (C) 2004 Novell, Inc
//
namespace Mono.CSharp
using System.IO;
using System.Text;
using System.Globalization;
++ using System.Xml;
++ using System.Diagnostics;
public enum Target {
Library, Exe, Module, WinExe
" -nostdlib[+|-] Does not load core libraries\n" +
" -nowarn:W1[,W2] Disables one or more warnings\n" +
" -out:FNAME Specifies output file\n" +
++ " -doc:XMLFILE Generates xml documentation into specified file\n" +
" -pkg:P1[,Pn] References packages P1..Pn\n" +
" --expect-error X Expect that error X will be encountered\n" +
" -recurse:SPEC Recursively compiles the files in SPEC ([dir]/file)\n" +
}
case "/doc": {
if (value == ""){
-- Report.Error (5, arg + " requires an argument");
++ Report.Error (2006, arg + " requires an argument");
Environment.Exit (1);
}
-- // TODO handle the /doc argument to generate xml doc
++ RootContext.Documentation = new Documentation (value);
return true;
}
case "/lib": {
if (timestamps)
ShowTime ("Resolving tree");
RootContext.ResolveTree ();
++
if (Report.Errors > 0)
return false;
if (timestamps)
RootContext.PopulateTypes ();
RootContext.DefineTypes ();
++ if (RootContext.Documentation != null &&
++ !RootContext.Documentation.OutputDocComment (
++ output_file))
++ return false;
++
TypeManager.InitCodeHelpers ();
//
#endif
return (Report.Errors == 0);
}
--
}
//
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;
++using System.Xml;
namespace Mono.CSharp {
protected override void VerifyObsoleteAttribute()
{
}
++
++ public override string DocCommentHeader {
++ get { return "F:"; }
++ }
}
/// <summary>
/// Enumeration container
/// </summary>
public class Enum : DeclSpace {
-- ArrayList ordered_enums;
++ public ArrayList ordered_enums;
public Expression BaseType;
/// Adds @name to the enumeration space, with @expr
/// being its definition.
/// </summary>
-- public void AddEnumMember (string name, Expression expr, Location loc, Attributes opt_attrs)
++ public void AddEnumMember (string name, Expression expr, Location loc, Attributes opt_attrs, string documentation)
{
if (name == "value__") {
Report.Error (76, loc, "An item in an enumeration can't have an identifier `value__'");
}
EnumMember em = new EnumMember (this, expr, name, loc, opt_attrs);
++ em.DocComment = documentation;
if (!AddToContainer (em, false, name, ""))
return;
{
// UnderlyingType is never obsolete
}
++
++ //
++ // Generates xml doc comments (if any), and if required,
++ // handle warning report.
++ //
++ internal override void GenerateDocComment (DeclSpace ds)
++ {
++ DocUtil.GenerateEnumDocComment (this, ds);
++ }
++
++ //
++ // Represents header string for documentation comment.
++ //
++ public override string DocCommentHeader {
++ get { return "T:"; }
++ }
}
}
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
++// (C) 2004 Novell, Inc
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
++using System.Xml;
namespace Mono.CSharp {
public static string StrongNameKeyContainer;
public static bool StrongNameDelaySign = false;
++ //
++ // If set, enable XML documentation generation
++ //
++ public static Documentation Documentation;
++
//
// Constructor
//