/// <summary> /// override of WriteDefAttribute /// </summary> public override void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode) { if (xamlDefAttributeNode.AttributeUsage == BamlAttributeUsage.RuntimeName) { string attributeValue = xamlDefAttributeNode.Value; if (!_pass2) { Debug.Assert(_name == null && _nameField == null, "Name definition has already been set"); _nameField = _compiler.AddNameField(attributeValue, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); _name = attributeValue; } if (_nameField != null || _compiler.IsRootNameScope) { WriteConnectionId(); // x:Name needs to be written out as a BAML record in order // to trigger the RegisterName code path in BamlRecordReader. // This code follows the code in WriteProperty for the RuntimeName property base.WriteDefAttribute(xamlDefAttributeNode); } } else if (xamlDefAttributeNode.Name == FIELDMODIFIER) { if (!_pass2) { _fieldModifier = _compiler.GetMemberAttributes(xamlDefAttributeNode.Value); _isFieldModifierSet = true; } } // Some x: attributes are processed by the compiler, but are unknown // to the base XamlParser. The compiler specific ones should not be passed // to XamlParser for processing, but the rest should be. else { bool isClass = xamlDefAttributeNode.Name == CLASS; bool isClassModifier = xamlDefAttributeNode.Name == CLASSMODIFIER; bool isTypeArgs = xamlDefAttributeNode.Name == XamlReaderHelper.DefinitionTypeArgs; bool isSubClass = xamlDefAttributeNode.Name == SUBCLASS; if (!isClass && !isClassModifier && !isTypeArgs && !isSubClass) { base.WriteDefAttribute(xamlDefAttributeNode); } else if (!_isRootTag) { ThrowException(SRID.DefinitionAttributeNotAllowed, MarkupCompiler.DefinitionNSPrefix, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } else if (isClass) { if (_class == MarkupCompiler.DOT) { int index = xamlDefAttributeNode.Value.LastIndexOf(MarkupCompiler.DOT, StringComparison.Ordinal); ThrowException(SRID.InvalidClassName, MarkupCompiler.DefinitionNSPrefix, CLASS, xamlDefAttributeNode.Value, index >= 0 ? "fully qualified " : string.Empty, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } _class = string.Empty; } else if (isClassModifier) { if (_classModifier == MarkupCompiler.DOT) { ThrowException(SRID.UnknownClassModifier, MarkupCompiler.DefinitionNSPrefix, xamlDefAttributeNode.Value, _compiler.Language, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } _classModifier = string.Empty; } else if (isSubClass) { if (_subClass == MarkupCompiler.DOT) { int index = xamlDefAttributeNode.Value.LastIndexOf(MarkupCompiler.DOT, StringComparison.Ordinal); ThrowException(SRID.InvalidClassName, MarkupCompiler.DefinitionNSPrefix, SUBCLASS, xamlDefAttributeNode.Value, index >= 0 ? "fully qualified " : string.Empty, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } _subClass = string.Empty; } else if (isTypeArgs) { _compiler.AddGenericArguments(ParserContext, xamlDefAttributeNode.Value); } } }
/// <summary> /// Write Def Attribute /// </summary> /// <remarks> /// Template parsing supports x:ID, so check for this here /// </remarks> public override void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode) { if (xamlDefAttributeNode.Name == BamlMapTable.NameString) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } } else { #if PBTCOMPILER // Remember that x:Key was read in, since this key has precedence over // the DataType="{x:Type SomeType}" key that may also be present. if (xamlDefAttributeNode.Name == XamlReaderHelper.DefinitionName && _styleModeStack.Mode == StyleMode.Base) { _defNameFound = true; } #endif base.WriteDefAttribute(xamlDefAttributeNode); } }
/// <summary> /// WriteDefAttribute when attributes of the form x:Whatever are encountered /// </summary> public virtual void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode) { string attributeValue = xamlDefAttributeNode.Value; // There are several known def attributes, and these are checked for // correctness by running the known type converters. switch(xamlDefAttributeNode.Name) { case XamlReaderHelper.DefinitionSynchronousMode: if (BamlRecordWriter != null) { if (xamlDefAttributeNode.Value == "Async") { ThrowException(SRID.ParserNoBamlAsync, "Async", xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); } } break; case XamlReaderHelper.DefinitionAsyncRecords: // Update the AsyncRecords and don't store this as a def attribute ThrowException(SRID.ParserNoBamlAsync, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); break; case XamlReaderHelper.DefinitionShared: Boolean.Parse(attributeValue); // For validation only. if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; case XamlReaderHelper.DefinitionUid: case XamlReaderHelper.DefinitionRuntimeName: //Error if x:Uid or x:Name are markup extensions if (MarkupExtensionParser.LooksLikeAMarkupExtension(attributeValue)) { string message = SR.Get(SRID.ParserBadUidOrNameME, attributeValue); message += " "; message += SR.Get(SRID.ParserLineAndOffset, xamlDefAttributeNode.LineNumber.ToString(CultureInfo.CurrentCulture), xamlDefAttributeNode.LinePosition.ToString(CultureInfo.CurrentCulture)); XamlParseException parseException = new XamlParseException(message, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); throw parseException; } if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; case XamlReaderHelper.DefinitionName: if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } break; default: string errorID; errorID = SRID.ParserUnknownDefAttribute; ThrowException(errorID, xamlDefAttributeNode.Name, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition); break; } }
/// <summary> /// A def attribute was encountered. Perform synchonous mode checking /// prior to calling the virtual that may be overridden. /// </summary> void WriteDefAttributeCore(XamlDefAttributeNode xamlDefAttributeNode) { string attributeValue = xamlDefAttributeNode.Value; switch(xamlDefAttributeNode.Name) { case XamlReaderHelper.DefinitionSynchronousMode: XamlParseMode documentParseMode = XamlParseMode.Synchronous; if (attributeValue.Equals("Async")) { documentParseMode = XamlParseMode.Asynchronous; } else if (attributeValue.Equals("[....]")) { documentParseMode = XamlParseMode.Synchronous; } else { ThrowException(SRID.ParserBadSyncMode, xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition ); } // if we haven't initialized the the parseMode yet set it if (XamlParseMode == XamlParseMode.Uninitialized) { // todo: for now hardcode the string. when finalized // should add a TypeConverter. XamlParseMode = documentParseMode; } break; default: break; } WriteDefAttribute(xamlDefAttributeNode); }
// Write a x:attribute="value" record. One typical use of this is // to specify the key to use when inserting the current object into // a Dictionary, but there can be other uses also internal void WriteDefAttribute(XamlDefAttributeNode xamlDefNode) { // If we are currently parsing a deferable content section, then check // to see if we have a dictionary key value here. If so, then store it // in the keys collection. if (_deferLoadingSupport && _deferElementDepth == 2 && xamlDefNode.Name == XamlReaderHelper.DefinitionName) { Debug.Assert(!InStaticResourceSection, "We do not support x:Key within a StaticResource Section"); // Note that if we get to here the assumption is that the value of the Name // attribute is *NOT* a MarkupExtension. A MarkupExtension would cause // WriteKeyElementStart being called. KeyDeferRecord keyRecord = (KeyDeferRecord)(_deferKeys[_deferKeys.Count-1]); BamlDefAttributeKeyStringRecord defKeyRecord = keyRecord.Record as BamlDefAttributeKeyStringRecord; if (defKeyRecord == null) { defKeyRecord = (BamlDefAttributeKeyStringRecord) BamlRecordManager.GetWriteRecord(BamlRecordType.DefAttributeKeyString); TransferOldSharedData(keyRecord.Record as IBamlDictionaryKey, defKeyRecord as IBamlDictionaryKey); keyRecord.Record = defKeyRecord; } // Store the string value in the string table, since there will mostly be a // [Static/Dynamic]Resource referring to it and we can combine the storage // for both these string into a single StringInfoRecord. short valueId; if (!MapTable.GetStringInfoId(xamlDefNode.Value, out valueId)) { valueId = MapTable.AddStringInfoMap(BinaryWriter, xamlDefNode.Value); } defKeyRecord.Value = xamlDefNode.Value; defKeyRecord.ValueId = valueId; keyRecord.LineNumber = xamlDefNode.LineNumber; keyRecord.LinePosition = xamlDefNode.LinePosition; return; } else if (_deferLoadingSupport && _deferElementDepth == 2 && xamlDefNode.Name == XamlReaderHelper.DefinitionShared) { Debug.Assert(!InStaticResourceSection, "We do not support x:Shared within a StaticResource Section"); // NOTE: This does not properly handle MarkupExtensions.... KeyDeferRecord keyRecord = (KeyDeferRecord)(_deferKeys[_deferKeys.Count-1]); IBamlDictionaryKey defKeyRecord = FindBamlDictionaryKey(keyRecord); if (defKeyRecord == null) { BamlDefAttributeKeyStringRecord defStringKeyRecord = (BamlDefAttributeKeyStringRecord) BamlRecordManager.GetWriteRecord(BamlRecordType.DefAttributeKeyString); keyRecord.Record = defStringKeyRecord; defKeyRecord = (IBamlDictionaryKey)defStringKeyRecord; } defKeyRecord.Shared = Boolean.Parse(xamlDefNode.Value); defKeyRecord.SharedSet = true; keyRecord.LineNumber = xamlDefNode.LineNumber; keyRecord.LinePosition = xamlDefNode.LinePosition; return; } // Add definition attribute record. Store the attribute name in the string table, since // the names are likely to be repeated. short stringId; if (!MapTable.GetStringInfoId(xamlDefNode.Name, out stringId)) { stringId = MapTable.AddStringInfoMap(BinaryWriter, xamlDefNode.Name); } BamlDefAttributeRecord defRecord = (BamlDefAttributeRecord) BamlRecordManager.GetWriteRecord(BamlRecordType.DefAttribute); defRecord.Value = xamlDefNode.Value; defRecord.Name = xamlDefNode.Name; defRecord.AttributeUsage = xamlDefNode.AttributeUsage; defRecord.NameId = stringId; WriteAndReleaseRecord(defRecord, xamlDefNode); }
/// <summary> /// Write Def Attribute /// </summary> /// <remarks> /// Style parsing supports x:ID, so check for this here /// </remarks> public override void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode) { if (xamlDefAttributeNode.Name == BamlMapTable.NameString) { if (BamlRecordWriter != null) { BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); } } else { #if PBTCOMPILER // Remember that x:Key was read in, since this key has precedence over // the TargetType="{x:Type SomeType}" key that may also be present. if (xamlDefAttributeNode.Name == XamlReaderHelper.DefinitionName && _styleModeStack.Mode == StyleMode.Base) { _defNameFound = true; } #endif // Skip Uids for EventSetter, since they are not localizable. if (!_inEventSetter || xamlDefAttributeNode.Name != XamlReaderHelper.DefinitionUid) { base.WriteDefAttribute(xamlDefAttributeNode); } } }
internal override ParserAction LoadNode(XamlNode tokenNode) { switch (tokenNode.TokenType) { case XamlNodeType.DocumentStart: { // A single ParserHooks might be used to parse multiple bamls. // We need to clear the comments list at the begining of each baml. _commentList.Clear(); _currentComment = new LocalizationComment(); return(ParserAction.Normal); } case XamlNodeType.DefAttribute: { XamlDefAttributeNode node = (XamlDefAttributeNode)tokenNode; if (node.Name == XamlReaderHelper.DefinitionUid) { _currentComment.Uid = node.Value; } return(ParserAction.Normal); } case XamlNodeType.Property: { XamlPropertyNode node = (XamlPropertyNode)tokenNode; // When this parer hook is invoked, comments is always output to a seperate file. if (LocComments.IsLocCommentsProperty(node.TypeFullName, node.PropName)) { // try parse the value. Exception will be thrown if not valid. LocComments.ParsePropertyComments(node.Value); _currentComment.Comments = node.Value; return(ParserAction.Skip); // skips outputing this node to baml } if (_directivesToFile == LocalizationDirectivesToLocFile.All && LocComments.IsLocLocalizabilityProperty(node.TypeFullName, node.PropName)) { // try parse the value. Exception will be thrown if not valid. LocComments.ParsePropertyLocalizabilityAttributes(node.Value); _currentComment.Attributes = node.Value; return(ParserAction.Skip); // skips outputing this node to baml } return(ParserAction.Normal); } case XamlNodeType.EndAttributes: { FlushCommentToList(ref _currentComment); return(ParserAction.Normal); } case XamlNodeType.DocumentEnd: { // // When reaching document end, we output all the comments we have collected // so far into a localization comment file. If the parsing was aborted in // MarkupCompilePass1, we would not out the incomplete set of comments because // it will not reach document end. // if (_commentList.Count > 0) { string absoluteOutputPath = _compiler.TargetPath + _compiler.SourceFileInfo.RelativeSourceFilePath + SharedStrings.LocExtension; MemoryStream memStream = new MemoryStream(); // TaskFileService.WriteFile adds BOM for UTF8 Encoding, thus don't add here // when creating XmlTextWriter. using (XmlTextWriter writer = new XmlTextWriter(memStream, new UTF8Encoding(false))) { // output XML for each piece of comment writer.Formatting = Formatting.Indented; writer.WriteStartElement(LocComments.LocResourcesElement); writer.WriteAttributeString(LocComments.LocFileNameAttribute, _compiler.SourceFileInfo.RelativeSourceFilePath); foreach (LocalizationComment comment in _commentList) { writer.WriteStartElement(LocComments.LocCommentsElement); writer.WriteAttributeString(LocComments.LocCommentIDAttribute, comment.Uid); if (comment.Attributes != null) { writer.WriteAttributeString(LocComments.LocLocalizabilityAttribute, comment.Attributes); } if (comment.Comments != null) { writer.WriteAttributeString(LocComments.LocCommentsAttribute, comment.Comments); } writer.WriteEndElement(); } writer.WriteEndElement(); writer.Flush(); _compiler.TaskFileService.WriteFile(memStream.ToArray(), absoluteOutputPath); } } return(ParserAction.Normal); } default: { return(ParserAction.Normal); } } }