diff options
author | Rob Mensching <rob@firegiant.com> | 2022-03-19 11:11:02 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2022-03-19 11:54:45 -0700 |
commit | 3e6d208dc34615d2e6428eb91ce16583eb331f7b (patch) | |
tree | 132080599eda8c14f13d5b73129ef387bd36195f | |
parent | dc634c5c0fa8d6c646d75be144cc546abc4b72c7 (diff) | |
download | wix-3e6d208dc34615d2e6428eb91ce16583eb331f7b.tar.gz wix-3e6d208dc34615d2e6428eb91ce16583eb331f7b.tar.bz2 wix-3e6d208dc34615d2e6428eb91ce16583eb331f7b.zip |
Refactor CustomTable parsing into separate partial and add test
Add a test for referencing custom tables and make the gigantic
Compiler.cs a bit smaller by extracting all the CustomTable handling
to separate partial.
4 files changed, 568 insertions, 507 deletions
diff --git a/src/wix/WixToolset.Core/Compiler.cs b/src/wix/WixToolset.Core/Compiler.cs index 5e2b3342..82faa9bb 100644 --- a/src/wix/WixToolset.Core/Compiler.cs +++ b/src/wix/WixToolset.Core/Compiler.cs | |||
@@ -3674,513 +3674,6 @@ namespace WixToolset.Core | |||
3674 | } | 3674 | } |
3675 | 3675 | ||
3676 | /// <summary> | 3676 | /// <summary> |
3677 | /// Parses a custom table element. | ||
3678 | /// </summary> | ||
3679 | /// <param name="node">Element to parse.</param> | ||
3680 | /// <remarks>not cleaned</remarks> | ||
3681 | private void ParseCustomTableElement(XElement node) | ||
3682 | { | ||
3683 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
3684 | string tableId = null; | ||
3685 | var unreal = false; | ||
3686 | var columns = new List<WixCustomTableColumnSymbol>(); | ||
3687 | var foundColumns = false; | ||
3688 | |||
3689 | foreach (var attrib in node.Attributes()) | ||
3690 | { | ||
3691 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
3692 | { | ||
3693 | switch (attrib.Name.LocalName) | ||
3694 | { | ||
3695 | case "Id": | ||
3696 | tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
3697 | break; | ||
3698 | case "Unreal": | ||
3699 | unreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
3700 | break; | ||
3701 | default: | ||
3702 | this.Core.UnexpectedAttribute(node, attrib); | ||
3703 | break; | ||
3704 | } | ||
3705 | } | ||
3706 | else | ||
3707 | { | ||
3708 | this.Core.ParseExtensionAttribute(node, attrib); | ||
3709 | } | ||
3710 | } | ||
3711 | |||
3712 | if (null == tableId) | ||
3713 | { | ||
3714 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
3715 | } | ||
3716 | else if (31 < tableId.Length) | ||
3717 | { | ||
3718 | this.Core.Write(ErrorMessages.CustomTableNameTooLong(sourceLineNumbers, node.Name.LocalName, "Id", tableId)); | ||
3719 | } | ||
3720 | |||
3721 | foreach (var child in node.Elements()) | ||
3722 | { | ||
3723 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
3724 | { | ||
3725 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
3726 | switch (child.Name.LocalName) | ||
3727 | { | ||
3728 | case "Column": | ||
3729 | foundColumns = true; | ||
3730 | |||
3731 | var column = this.ParseColumnElement(child, childSourceLineNumbers, tableId); | ||
3732 | if (column != null) | ||
3733 | { | ||
3734 | columns.Add(column); | ||
3735 | } | ||
3736 | break; | ||
3737 | case "Row": | ||
3738 | this.ParseRowElement(child, childSourceLineNumbers, tableId); | ||
3739 | break; | ||
3740 | default: | ||
3741 | this.Core.UnexpectedElement(node, child); | ||
3742 | break; | ||
3743 | } | ||
3744 | } | ||
3745 | else | ||
3746 | { | ||
3747 | this.Core.ParseExtensionElement(node, child); | ||
3748 | } | ||
3749 | } | ||
3750 | |||
3751 | if (columns.Count > 0) | ||
3752 | { | ||
3753 | if (!columns.Where(c => c.PrimaryKey).Any()) | ||
3754 | { | ||
3755 | this.Core.Write(ErrorMessages.CustomTableMissingPrimaryKey(sourceLineNumbers)); | ||
3756 | } | ||
3757 | |||
3758 | if (!this.Core.EncounteredError) | ||
3759 | { | ||
3760 | var columnNames = String.Join(new string(WixCustomTableSymbol.ColumnNamesSeparator, 1), columns.Select(c => c.Name)); | ||
3761 | |||
3762 | this.Core.AddSymbol(new WixCustomTableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, tableId)) | ||
3763 | { | ||
3764 | ColumnNames = columnNames, | ||
3765 | Unreal = unreal, | ||
3766 | }); | ||
3767 | } | ||
3768 | else if (!foundColumns) | ||
3769 | { | ||
3770 | this.Core.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, node.Name.LocalName, "Column")); | ||
3771 | } | ||
3772 | } | ||
3773 | } | ||
3774 | |||
3775 | /// <summary> | ||
3776 | /// Parses a CustomTableRef element. | ||
3777 | /// </summary> | ||
3778 | /// <param name="node">Element to parse.</param> | ||
3779 | private void ParseCustomTableRefElement(XElement node) | ||
3780 | { | ||
3781 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
3782 | string tableId = null; | ||
3783 | |||
3784 | foreach (var attrib in node.Attributes()) | ||
3785 | { | ||
3786 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
3787 | { | ||
3788 | switch (attrib.Name.LocalName) | ||
3789 | { | ||
3790 | case "Id": | ||
3791 | tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
3792 | this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.WixCustomTable, tableId); | ||
3793 | break; | ||
3794 | default: | ||
3795 | this.Core.UnexpectedAttribute(node, attrib); | ||
3796 | break; | ||
3797 | } | ||
3798 | } | ||
3799 | else | ||
3800 | { | ||
3801 | this.Core.ParseExtensionAttribute(node, attrib); | ||
3802 | } | ||
3803 | } | ||
3804 | |||
3805 | if (null == tableId) | ||
3806 | { | ||
3807 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
3808 | } | ||
3809 | |||
3810 | foreach (var child in node.Elements()) | ||
3811 | { | ||
3812 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
3813 | { | ||
3814 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
3815 | switch (child.Name.LocalName) | ||
3816 | { | ||
3817 | case "Row": | ||
3818 | this.ParseRowElement(child, childSourceLineNumbers, tableId); | ||
3819 | break; | ||
3820 | default: | ||
3821 | this.Core.UnexpectedElement(node, child); | ||
3822 | break; | ||
3823 | } | ||
3824 | } | ||
3825 | else | ||
3826 | { | ||
3827 | this.Core.ParseExtensionElement(node, child); | ||
3828 | } | ||
3829 | } | ||
3830 | } | ||
3831 | |||
3832 | /// <summary> | ||
3833 | /// Parses a Column element. | ||
3834 | /// </summary> | ||
3835 | /// <param name="child">Element to parse.</param> | ||
3836 | /// <param name="childSourceLineNumbers">Element's SourceLineNumbers.</param> | ||
3837 | /// <param name="tableId">Table Id.</param> | ||
3838 | private WixCustomTableColumnSymbol ParseColumnElement(XElement child, SourceLineNumber childSourceLineNumbers, string tableId) | ||
3839 | { | ||
3840 | string columnName = null; | ||
3841 | IntermediateFieldType? columnType = null; | ||
3842 | var description = String.Empty; | ||
3843 | int? keyColumn = null; | ||
3844 | var keyTable = String.Empty; | ||
3845 | var localizable = false; | ||
3846 | long? maxValue = null; | ||
3847 | long? minValue = null; | ||
3848 | WixCustomTableColumnCategoryType? category = null; | ||
3849 | var modularization = WixCustomTableColumnModularizeType.None; | ||
3850 | var nullable = false; | ||
3851 | var primaryKey = false; | ||
3852 | var setValues = String.Empty; | ||
3853 | var columnUnreal = false; | ||
3854 | var width = 0; | ||
3855 | |||
3856 | foreach (var childAttrib in child.Attributes()) | ||
3857 | { | ||
3858 | switch (childAttrib.Name.LocalName) | ||
3859 | { | ||
3860 | case "Id": | ||
3861 | columnName = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, childAttrib); | ||
3862 | break; | ||
3863 | case "Category": | ||
3864 | var categoryValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
3865 | switch (categoryValue) | ||
3866 | { | ||
3867 | case "text": | ||
3868 | category = WixCustomTableColumnCategoryType.Text; | ||
3869 | break; | ||
3870 | case "upperCase": | ||
3871 | category = WixCustomTableColumnCategoryType.UpperCase; | ||
3872 | break; | ||
3873 | case "lowerCase": | ||
3874 | category = WixCustomTableColumnCategoryType.LowerCase; | ||
3875 | break; | ||
3876 | case "integer": | ||
3877 | category = WixCustomTableColumnCategoryType.Integer; | ||
3878 | break; | ||
3879 | case "doubleInteger": | ||
3880 | category = WixCustomTableColumnCategoryType.DoubleInteger; | ||
3881 | break; | ||
3882 | case "timeDate": | ||
3883 | category = WixCustomTableColumnCategoryType.TimeDate; | ||
3884 | break; | ||
3885 | case "identifier": | ||
3886 | category = WixCustomTableColumnCategoryType.Identifier; | ||
3887 | break; | ||
3888 | case "property": | ||
3889 | category = WixCustomTableColumnCategoryType.Property; | ||
3890 | break; | ||
3891 | case "filename": | ||
3892 | category = WixCustomTableColumnCategoryType.Filename; | ||
3893 | break; | ||
3894 | case "wildCardFilename": | ||
3895 | category = WixCustomTableColumnCategoryType.WildCardFilename; | ||
3896 | break; | ||
3897 | case "path": | ||
3898 | category = WixCustomTableColumnCategoryType.Path; | ||
3899 | break; | ||
3900 | case "paths": | ||
3901 | category = WixCustomTableColumnCategoryType.Paths; | ||
3902 | break; | ||
3903 | case "anyPath": | ||
3904 | category = WixCustomTableColumnCategoryType.AnyPath; | ||
3905 | break; | ||
3906 | case "defaultDir": | ||
3907 | category = WixCustomTableColumnCategoryType.DefaultDir; | ||
3908 | break; | ||
3909 | case "regPath": | ||
3910 | category = WixCustomTableColumnCategoryType.RegPath; | ||
3911 | break; | ||
3912 | case "formatted": | ||
3913 | category = WixCustomTableColumnCategoryType.Formatted; | ||
3914 | break; | ||
3915 | case "formattedSddl": | ||
3916 | category = WixCustomTableColumnCategoryType.FormattedSddl; | ||
3917 | break; | ||
3918 | case "template": | ||
3919 | category = WixCustomTableColumnCategoryType.Template; | ||
3920 | break; | ||
3921 | case "condition": | ||
3922 | category = WixCustomTableColumnCategoryType.Condition; | ||
3923 | break; | ||
3924 | case "guid": | ||
3925 | category = WixCustomTableColumnCategoryType.Guid; | ||
3926 | break; | ||
3927 | case "version": | ||
3928 | category = WixCustomTableColumnCategoryType.Version; | ||
3929 | break; | ||
3930 | case "language": | ||
3931 | category = WixCustomTableColumnCategoryType.Language; | ||
3932 | break; | ||
3933 | case "binary": | ||
3934 | category = WixCustomTableColumnCategoryType.Binary; | ||
3935 | break; | ||
3936 | case "customSource": | ||
3937 | category = WixCustomTableColumnCategoryType.CustomSource; | ||
3938 | break; | ||
3939 | case "cabinet": | ||
3940 | category = WixCustomTableColumnCategoryType.Cabinet; | ||
3941 | break; | ||
3942 | case "shortcut": | ||
3943 | category = WixCustomTableColumnCategoryType.Shortcut; | ||
3944 | break; | ||
3945 | case "": | ||
3946 | break; | ||
3947 | default: | ||
3948 | this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Category", categoryValue, | ||
3949 | "text", "upperCase", "lowerCase", "integer", "doubleInteger", "timeDate", "identifier", "property", "filename", | ||
3950 | "wildCardFilename", "path", "paths", "anyPath", "defaultDir", "regPath", "formatted", "formattedSddl", "template", | ||
3951 | "condition", "guid", "version", "language", "binary", "customSource", "cabinet", "shortcut")); | ||
3952 | columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. | ||
3953 | break; | ||
3954 | } | ||
3955 | break; | ||
3956 | case "Description": | ||
3957 | description = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
3958 | break; | ||
3959 | case "KeyColumn": | ||
3960 | keyColumn = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 1, 32); | ||
3961 | break; | ||
3962 | case "KeyTable": | ||
3963 | keyTable = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
3964 | break; | ||
3965 | case "Localizable": | ||
3966 | localizable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
3967 | break; | ||
3968 | case "MaxValue": | ||
3969 | maxValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue); | ||
3970 | break; | ||
3971 | case "MinValue": | ||
3972 | minValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue); | ||
3973 | break; | ||
3974 | case "Modularize": | ||
3975 | var modularizeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
3976 | switch (modularizeValue) | ||
3977 | { | ||
3978 | case "column": | ||
3979 | modularization = WixCustomTableColumnModularizeType.Column; | ||
3980 | break; | ||
3981 | case "companionFile": | ||
3982 | modularization = WixCustomTableColumnModularizeType.CompanionFile; | ||
3983 | break; | ||
3984 | case "condition": | ||
3985 | modularization = WixCustomTableColumnModularizeType.Condition; | ||
3986 | break; | ||
3987 | case "controlEventArgument": | ||
3988 | modularization = WixCustomTableColumnModularizeType.ControlEventArgument; | ||
3989 | break; | ||
3990 | case "controlText": | ||
3991 | modularization = WixCustomTableColumnModularizeType.ControlText; | ||
3992 | break; | ||
3993 | case "icon": | ||
3994 | modularization = WixCustomTableColumnModularizeType.Icon; | ||
3995 | break; | ||
3996 | case "none": | ||
3997 | modularization = WixCustomTableColumnModularizeType.None; | ||
3998 | break; | ||
3999 | case "property": | ||
4000 | modularization = WixCustomTableColumnModularizeType.Property; | ||
4001 | break; | ||
4002 | case "semicolonDelimited": | ||
4003 | modularization = WixCustomTableColumnModularizeType.SemicolonDelimited; | ||
4004 | break; | ||
4005 | case "": | ||
4006 | break; | ||
4007 | default: | ||
4008 | this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Modularize", modularizeValue, "column", "companionFile", "condition", "controlEventArgument", "controlText", "icon", "property", "semicolonDelimited")); | ||
4009 | columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. | ||
4010 | break; | ||
4011 | } | ||
4012 | break; | ||
4013 | case "Nullable": | ||
4014 | nullable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
4015 | break; | ||
4016 | case "PrimaryKey": | ||
4017 | primaryKey = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
4018 | break; | ||
4019 | case "Set": | ||
4020 | setValues = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
4021 | break; | ||
4022 | case "Type": | ||
4023 | var typeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
4024 | switch (typeValue) | ||
4025 | { | ||
4026 | case "binary": | ||
4027 | columnType = IntermediateFieldType.Path; | ||
4028 | break; | ||
4029 | case "int": | ||
4030 | columnType = IntermediateFieldType.Number; | ||
4031 | break; | ||
4032 | case "string": | ||
4033 | columnType = IntermediateFieldType.String; | ||
4034 | break; | ||
4035 | case "": | ||
4036 | break; | ||
4037 | default: | ||
4038 | this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Type", typeValue, "binary", "int", "string")); | ||
4039 | columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. | ||
4040 | break; | ||
4041 | } | ||
4042 | break; | ||
4043 | case "Width": | ||
4044 | width = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 0, Int32.MaxValue); | ||
4045 | break; | ||
4046 | case "Unreal": | ||
4047 | columnUnreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
4048 | break; | ||
4049 | default: | ||
4050 | this.Core.UnexpectedAttribute(child, childAttrib); | ||
4051 | break; | ||
4052 | } | ||
4053 | } | ||
4054 | |||
4055 | if (null == columnName) | ||
4056 | { | ||
4057 | this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Id")); | ||
4058 | } | ||
4059 | |||
4060 | if (!columnType.HasValue) | ||
4061 | { | ||
4062 | this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Type")); | ||
4063 | } | ||
4064 | else if (columnType == IntermediateFieldType.Number) | ||
4065 | { | ||
4066 | if (2 != width && 4 != width) | ||
4067 | { | ||
4068 | this.Core.Write(ErrorMessages.CustomTableIllegalColumnWidth(childSourceLineNumbers, child.Name.LocalName, "Width", width)); | ||
4069 | } | ||
4070 | } | ||
4071 | else if (columnType == IntermediateFieldType.Path) | ||
4072 | { | ||
4073 | if (!category.HasValue) | ||
4074 | { | ||
4075 | category = WixCustomTableColumnCategoryType.Binary; | ||
4076 | } | ||
4077 | else if (category != WixCustomTableColumnCategoryType.Binary) | ||
4078 | { | ||
4079 | this.Core.Write(ErrorMessages.ExpectedBinaryCategory(childSourceLineNumbers)); | ||
4080 | } | ||
4081 | } | ||
4082 | |||
4083 | this.Core.ParseForExtensionElements(child); | ||
4084 | |||
4085 | if (this.Core.EncounteredError) | ||
4086 | { | ||
4087 | return null; | ||
4088 | } | ||
4089 | |||
4090 | var attributes = primaryKey ? WixCustomTableColumnSymbolAttributes.PrimaryKey : WixCustomTableColumnSymbolAttributes.None; | ||
4091 | attributes |= localizable ? WixCustomTableColumnSymbolAttributes.Localizable : WixCustomTableColumnSymbolAttributes.None; | ||
4092 | attributes |= nullable ? WixCustomTableColumnSymbolAttributes.Nullable : WixCustomTableColumnSymbolAttributes.None; | ||
4093 | attributes |= columnUnreal ? WixCustomTableColumnSymbolAttributes.Unreal : WixCustomTableColumnSymbolAttributes.None; | ||
4094 | |||
4095 | var column = this.Core.AddSymbol(new WixCustomTableColumnSymbol(childSourceLineNumbers, new Identifier(AccessModifier.Section, tableId, columnName)) | ||
4096 | { | ||
4097 | TableRef = tableId, | ||
4098 | Name = columnName, | ||
4099 | Type = columnType.Value, | ||
4100 | Attributes = attributes, | ||
4101 | Width = width, | ||
4102 | Category = category, | ||
4103 | Description = description, | ||
4104 | KeyColumn = keyColumn, | ||
4105 | KeyTable = keyTable, | ||
4106 | MaxValue = maxValue, | ||
4107 | MinValue = minValue, | ||
4108 | Modularize = modularization, | ||
4109 | Set = setValues, | ||
4110 | }); | ||
4111 | return column; | ||
4112 | } | ||
4113 | |||
4114 | /// <summary> | ||
4115 | /// Parses a Row element. | ||
4116 | /// </summary> | ||
4117 | /// <param name="node">Element to parse.</param> | ||
4118 | /// <param name="sourceLineNumbers">Element's SourceLineNumbers.</param> | ||
4119 | /// <param name="tableId">Table Id.</param> | ||
4120 | private void ParseRowElement(XElement node, SourceLineNumber sourceLineNumbers, string tableId) | ||
4121 | { | ||
4122 | var rowId = Guid.NewGuid().ToString("N").ToUpperInvariant(); | ||
4123 | |||
4124 | foreach (var attrib in node.Attributes()) | ||
4125 | { | ||
4126 | this.Core.ParseExtensionAttribute(node, attrib); | ||
4127 | } | ||
4128 | |||
4129 | foreach (var child in node.Elements()) | ||
4130 | { | ||
4131 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
4132 | switch (child.Name.LocalName) | ||
4133 | { | ||
4134 | case "Data": | ||
4135 | string columnName = null; | ||
4136 | string data = null; | ||
4137 | foreach (var attrib in child.Attributes()) | ||
4138 | { | ||
4139 | switch (attrib.Name.LocalName) | ||
4140 | { | ||
4141 | case "Column": | ||
4142 | columnName = this.Core.GetAttributeValue(childSourceLineNumbers, attrib); | ||
4143 | break; | ||
4144 | case "Value": | ||
4145 | data = this.Core.GetAttributeValue(childSourceLineNumbers, attrib); | ||
4146 | break; | ||
4147 | default: | ||
4148 | this.Core.ParseExtensionAttribute(child, attrib); | ||
4149 | break; | ||
4150 | } | ||
4151 | } | ||
4152 | |||
4153 | this.Core.InnerTextDisallowed(node); | ||
4154 | |||
4155 | if (null == columnName) | ||
4156 | { | ||
4157 | this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Column")); | ||
4158 | } | ||
4159 | |||
4160 | if (!this.Core.EncounteredError) | ||
4161 | { | ||
4162 | this.Core.AddSymbol(new WixCustomTableCellSymbol(childSourceLineNumbers, new Identifier(AccessModifier.Section, tableId, rowId, columnName)) | ||
4163 | { | ||
4164 | RowId = rowId, | ||
4165 | ColumnRef = columnName, | ||
4166 | TableRef = tableId, | ||
4167 | Data = data | ||
4168 | }); | ||
4169 | } | ||
4170 | break; | ||
4171 | default: | ||
4172 | this.Core.UnexpectedElement(node, child); | ||
4173 | break; | ||
4174 | } | ||
4175 | } | ||
4176 | |||
4177 | if (!this.Core.EncounteredError) | ||
4178 | { | ||
4179 | this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.WixCustomTable, tableId); | ||
4180 | } | ||
4181 | } | ||
4182 | |||
4183 | /// <summary> | ||
4184 | /// Parses a directory element. | 3677 | /// Parses a directory element. |
4185 | /// </summary> | 3678 | /// </summary> |
4186 | /// <param name="node">Element to parse.</param> | 3679 | /// <param name="node">Element to parse.</param> |
diff --git a/src/wix/WixToolset.Core/Compiler_CustomTable.cs b/src/wix/WixToolset.Core/Compiler_CustomTable.cs new file mode 100644 index 00000000..cdb1c99a --- /dev/null +++ b/src/wix/WixToolset.Core/Compiler_CustomTable.cs | |||
@@ -0,0 +1,520 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Linq; | ||
8 | using System.Xml.Linq; | ||
9 | using WixToolset.Data; | ||
10 | using WixToolset.Data.Symbols; | ||
11 | |||
12 | /// <summary> | ||
13 | /// Compiler of the WiX toolset. | ||
14 | /// </summary> | ||
15 | internal partial class Compiler : ICompiler | ||
16 | { | ||
17 | /// <summary> | ||
18 | /// Parses a custom table element. | ||
19 | /// </summary> | ||
20 | /// <param name="node">Element to parse.</param> | ||
21 | /// <remarks>not cleaned</remarks> | ||
22 | private void ParseCustomTableElement(XElement node) | ||
23 | { | ||
24 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
25 | string tableId = null; | ||
26 | var unreal = false; | ||
27 | var columns = new List<WixCustomTableColumnSymbol>(); | ||
28 | var foundColumns = false; | ||
29 | |||
30 | foreach (var attrib in node.Attributes()) | ||
31 | { | ||
32 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
33 | { | ||
34 | switch (attrib.Name.LocalName) | ||
35 | { | ||
36 | case "Id": | ||
37 | tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
38 | break; | ||
39 | case "Unreal": | ||
40 | unreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); | ||
41 | break; | ||
42 | default: | ||
43 | this.Core.UnexpectedAttribute(node, attrib); | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | else | ||
48 | { | ||
49 | this.Core.ParseExtensionAttribute(node, attrib); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | if (null == tableId) | ||
54 | { | ||
55 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
56 | } | ||
57 | else if (31 < tableId.Length) | ||
58 | { | ||
59 | this.Core.Write(ErrorMessages.CustomTableNameTooLong(sourceLineNumbers, node.Name.LocalName, "Id", tableId)); | ||
60 | } | ||
61 | |||
62 | foreach (var child in node.Elements()) | ||
63 | { | ||
64 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
65 | { | ||
66 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
67 | switch (child.Name.LocalName) | ||
68 | { | ||
69 | case "Column": | ||
70 | foundColumns = true; | ||
71 | |||
72 | var column = this.ParseColumnElement(child, childSourceLineNumbers, tableId); | ||
73 | if (column != null) | ||
74 | { | ||
75 | columns.Add(column); | ||
76 | } | ||
77 | break; | ||
78 | case "Row": | ||
79 | this.ParseRowElement(child, childSourceLineNumbers, tableId); | ||
80 | break; | ||
81 | default: | ||
82 | this.Core.UnexpectedElement(node, child); | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | else | ||
87 | { | ||
88 | this.Core.ParseExtensionElement(node, child); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | if (columns.Count > 0) | ||
93 | { | ||
94 | if (!columns.Where(c => c.PrimaryKey).Any()) | ||
95 | { | ||
96 | this.Core.Write(ErrorMessages.CustomTableMissingPrimaryKey(sourceLineNumbers)); | ||
97 | } | ||
98 | |||
99 | if (!this.Core.EncounteredError) | ||
100 | { | ||
101 | var columnNames = String.Join(new string(WixCustomTableSymbol.ColumnNamesSeparator, 1), columns.Select(c => c.Name)); | ||
102 | |||
103 | this.Core.AddSymbol(new WixCustomTableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, tableId)) | ||
104 | { | ||
105 | ColumnNames = columnNames, | ||
106 | Unreal = unreal, | ||
107 | }); | ||
108 | } | ||
109 | else if (!foundColumns) | ||
110 | { | ||
111 | this.Core.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, node.Name.LocalName, "Column")); | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /// <summary> | ||
117 | /// Parses a CustomTableRef element. | ||
118 | /// </summary> | ||
119 | /// <param name="node">Element to parse.</param> | ||
120 | private void ParseCustomTableRefElement(XElement node) | ||
121 | { | ||
122 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
123 | string tableId = null; | ||
124 | |||
125 | foreach (var attrib in node.Attributes()) | ||
126 | { | ||
127 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
128 | { | ||
129 | switch (attrib.Name.LocalName) | ||
130 | { | ||
131 | case "Id": | ||
132 | tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
133 | this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.WixCustomTable, tableId); | ||
134 | this.Core.EnsureTable(sourceLineNumbers, tableId); | ||
135 | break; | ||
136 | default: | ||
137 | this.Core.UnexpectedAttribute(node, attrib); | ||
138 | break; | ||
139 | } | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | this.Core.ParseExtensionAttribute(node, attrib); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | if (null == tableId) | ||
148 | { | ||
149 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
150 | } | ||
151 | |||
152 | foreach (var child in node.Elements()) | ||
153 | { | ||
154 | if (CompilerCore.WixNamespace == child.Name.Namespace) | ||
155 | { | ||
156 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
157 | switch (child.Name.LocalName) | ||
158 | { | ||
159 | case "Row": | ||
160 | this.ParseRowElement(child, childSourceLineNumbers, tableId); | ||
161 | break; | ||
162 | default: | ||
163 | this.Core.UnexpectedElement(node, child); | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | this.Core.ParseExtensionElement(node, child); | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
174 | /// <summary> | ||
175 | /// Parses a Column element. | ||
176 | /// </summary> | ||
177 | /// <param name="child">Element to parse.</param> | ||
178 | /// <param name="childSourceLineNumbers">Element's SourceLineNumbers.</param> | ||
179 | /// <param name="tableId">Table Id.</param> | ||
180 | private WixCustomTableColumnSymbol ParseColumnElement(XElement child, SourceLineNumber childSourceLineNumbers, string tableId) | ||
181 | { | ||
182 | string columnName = null; | ||
183 | IntermediateFieldType? columnType = null; | ||
184 | var description = String.Empty; | ||
185 | int? keyColumn = null; | ||
186 | var keyTable = String.Empty; | ||
187 | var localizable = false; | ||
188 | long? maxValue = null; | ||
189 | long? minValue = null; | ||
190 | WixCustomTableColumnCategoryType? category = null; | ||
191 | var modularization = WixCustomTableColumnModularizeType.None; | ||
192 | var nullable = false; | ||
193 | var primaryKey = false; | ||
194 | var setValues = String.Empty; | ||
195 | var columnUnreal = false; | ||
196 | var width = 0; | ||
197 | |||
198 | foreach (var childAttrib in child.Attributes()) | ||
199 | { | ||
200 | switch (childAttrib.Name.LocalName) | ||
201 | { | ||
202 | case "Id": | ||
203 | columnName = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, childAttrib); | ||
204 | break; | ||
205 | case "Category": | ||
206 | var categoryValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
207 | switch (categoryValue) | ||
208 | { | ||
209 | case "text": | ||
210 | category = WixCustomTableColumnCategoryType.Text; | ||
211 | break; | ||
212 | case "upperCase": | ||
213 | category = WixCustomTableColumnCategoryType.UpperCase; | ||
214 | break; | ||
215 | case "lowerCase": | ||
216 | category = WixCustomTableColumnCategoryType.LowerCase; | ||
217 | break; | ||
218 | case "integer": | ||
219 | category = WixCustomTableColumnCategoryType.Integer; | ||
220 | break; | ||
221 | case "doubleInteger": | ||
222 | category = WixCustomTableColumnCategoryType.DoubleInteger; | ||
223 | break; | ||
224 | case "timeDate": | ||
225 | category = WixCustomTableColumnCategoryType.TimeDate; | ||
226 | break; | ||
227 | case "identifier": | ||
228 | category = WixCustomTableColumnCategoryType.Identifier; | ||
229 | break; | ||
230 | case "property": | ||
231 | category = WixCustomTableColumnCategoryType.Property; | ||
232 | break; | ||
233 | case "filename": | ||
234 | category = WixCustomTableColumnCategoryType.Filename; | ||
235 | break; | ||
236 | case "wildCardFilename": | ||
237 | category = WixCustomTableColumnCategoryType.WildCardFilename; | ||
238 | break; | ||
239 | case "path": | ||
240 | category = WixCustomTableColumnCategoryType.Path; | ||
241 | break; | ||
242 | case "paths": | ||
243 | category = WixCustomTableColumnCategoryType.Paths; | ||
244 | break; | ||
245 | case "anyPath": | ||
246 | category = WixCustomTableColumnCategoryType.AnyPath; | ||
247 | break; | ||
248 | case "defaultDir": | ||
249 | category = WixCustomTableColumnCategoryType.DefaultDir; | ||
250 | break; | ||
251 | case "regPath": | ||
252 | category = WixCustomTableColumnCategoryType.RegPath; | ||
253 | break; | ||
254 | case "formatted": | ||
255 | category = WixCustomTableColumnCategoryType.Formatted; | ||
256 | break; | ||
257 | case "formattedSddl": | ||
258 | category = WixCustomTableColumnCategoryType.FormattedSddl; | ||
259 | break; | ||
260 | case "template": | ||
261 | category = WixCustomTableColumnCategoryType.Template; | ||
262 | break; | ||
263 | case "condition": | ||
264 | category = WixCustomTableColumnCategoryType.Condition; | ||
265 | break; | ||
266 | case "guid": | ||
267 | category = WixCustomTableColumnCategoryType.Guid; | ||
268 | break; | ||
269 | case "version": | ||
270 | category = WixCustomTableColumnCategoryType.Version; | ||
271 | break; | ||
272 | case "language": | ||
273 | category = WixCustomTableColumnCategoryType.Language; | ||
274 | break; | ||
275 | case "binary": | ||
276 | category = WixCustomTableColumnCategoryType.Binary; | ||
277 | break; | ||
278 | case "customSource": | ||
279 | category = WixCustomTableColumnCategoryType.CustomSource; | ||
280 | break; | ||
281 | case "cabinet": | ||
282 | category = WixCustomTableColumnCategoryType.Cabinet; | ||
283 | break; | ||
284 | case "shortcut": | ||
285 | category = WixCustomTableColumnCategoryType.Shortcut; | ||
286 | break; | ||
287 | case "": | ||
288 | break; | ||
289 | default: | ||
290 | this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Category", categoryValue, | ||
291 | "text", "upperCase", "lowerCase", "integer", "doubleInteger", "timeDate", "identifier", "property", "filename", | ||
292 | "wildCardFilename", "path", "paths", "anyPath", "defaultDir", "regPath", "formatted", "formattedSddl", "template", | ||
293 | "condition", "guid", "version", "language", "binary", "customSource", "cabinet", "shortcut")); | ||
294 | columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. | ||
295 | break; | ||
296 | } | ||
297 | break; | ||
298 | case "Description": | ||
299 | description = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
300 | break; | ||
301 | case "KeyColumn": | ||
302 | keyColumn = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 1, 32); | ||
303 | break; | ||
304 | case "KeyTable": | ||
305 | keyTable = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
306 | break; | ||
307 | case "Localizable": | ||
308 | localizable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
309 | break; | ||
310 | case "MaxValue": | ||
311 | maxValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue); | ||
312 | break; | ||
313 | case "MinValue": | ||
314 | minValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue); | ||
315 | break; | ||
316 | case "Modularize": | ||
317 | var modularizeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
318 | switch (modularizeValue) | ||
319 | { | ||
320 | case "column": | ||
321 | modularization = WixCustomTableColumnModularizeType.Column; | ||
322 | break; | ||
323 | case "companionFile": | ||
324 | modularization = WixCustomTableColumnModularizeType.CompanionFile; | ||
325 | break; | ||
326 | case "condition": | ||
327 | modularization = WixCustomTableColumnModularizeType.Condition; | ||
328 | break; | ||
329 | case "controlEventArgument": | ||
330 | modularization = WixCustomTableColumnModularizeType.ControlEventArgument; | ||
331 | break; | ||
332 | case "controlText": | ||
333 | modularization = WixCustomTableColumnModularizeType.ControlText; | ||
334 | break; | ||
335 | case "icon": | ||
336 | modularization = WixCustomTableColumnModularizeType.Icon; | ||
337 | break; | ||
338 | case "none": | ||
339 | modularization = WixCustomTableColumnModularizeType.None; | ||
340 | break; | ||
341 | case "property": | ||
342 | modularization = WixCustomTableColumnModularizeType.Property; | ||
343 | break; | ||
344 | case "semicolonDelimited": | ||
345 | modularization = WixCustomTableColumnModularizeType.SemicolonDelimited; | ||
346 | break; | ||
347 | case "": | ||
348 | break; | ||
349 | default: | ||
350 | this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Modularize", modularizeValue, "column", "companionFile", "condition", "controlEventArgument", "controlText", "icon", "property", "semicolonDelimited")); | ||
351 | columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. | ||
352 | break; | ||
353 | } | ||
354 | break; | ||
355 | case "Nullable": | ||
356 | nullable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
357 | break; | ||
358 | case "PrimaryKey": | ||
359 | primaryKey = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
360 | break; | ||
361 | case "Set": | ||
362 | setValues = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
363 | break; | ||
364 | case "Type": | ||
365 | var typeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); | ||
366 | switch (typeValue) | ||
367 | { | ||
368 | case "binary": | ||
369 | columnType = IntermediateFieldType.Path; | ||
370 | break; | ||
371 | case "int": | ||
372 | columnType = IntermediateFieldType.Number; | ||
373 | break; | ||
374 | case "string": | ||
375 | columnType = IntermediateFieldType.String; | ||
376 | break; | ||
377 | case "": | ||
378 | break; | ||
379 | default: | ||
380 | this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Type", typeValue, "binary", "int", "string")); | ||
381 | columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. | ||
382 | break; | ||
383 | } | ||
384 | break; | ||
385 | case "Width": | ||
386 | width = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 0, Int32.MaxValue); | ||
387 | break; | ||
388 | case "Unreal": | ||
389 | columnUnreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); | ||
390 | break; | ||
391 | default: | ||
392 | this.Core.UnexpectedAttribute(child, childAttrib); | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | if (null == columnName) | ||
398 | { | ||
399 | this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Id")); | ||
400 | } | ||
401 | |||
402 | if (!columnType.HasValue) | ||
403 | { | ||
404 | this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Type")); | ||
405 | } | ||
406 | else if (columnType == IntermediateFieldType.Number) | ||
407 | { | ||
408 | if (2 != width && 4 != width) | ||
409 | { | ||
410 | this.Core.Write(ErrorMessages.CustomTableIllegalColumnWidth(childSourceLineNumbers, child.Name.LocalName, "Width", width)); | ||
411 | } | ||
412 | } | ||
413 | else if (columnType == IntermediateFieldType.Path) | ||
414 | { | ||
415 | if (!category.HasValue) | ||
416 | { | ||
417 | category = WixCustomTableColumnCategoryType.Binary; | ||
418 | } | ||
419 | else if (category != WixCustomTableColumnCategoryType.Binary) | ||
420 | { | ||
421 | this.Core.Write(ErrorMessages.ExpectedBinaryCategory(childSourceLineNumbers)); | ||
422 | } | ||
423 | } | ||
424 | |||
425 | this.Core.ParseForExtensionElements(child); | ||
426 | |||
427 | if (this.Core.EncounteredError) | ||
428 | { | ||
429 | return null; | ||
430 | } | ||
431 | |||
432 | var attributes = primaryKey ? WixCustomTableColumnSymbolAttributes.PrimaryKey : WixCustomTableColumnSymbolAttributes.None; | ||
433 | attributes |= localizable ? WixCustomTableColumnSymbolAttributes.Localizable : WixCustomTableColumnSymbolAttributes.None; | ||
434 | attributes |= nullable ? WixCustomTableColumnSymbolAttributes.Nullable : WixCustomTableColumnSymbolAttributes.None; | ||
435 | attributes |= columnUnreal ? WixCustomTableColumnSymbolAttributes.Unreal : WixCustomTableColumnSymbolAttributes.None; | ||
436 | |||
437 | var column = this.Core.AddSymbol(new WixCustomTableColumnSymbol(childSourceLineNumbers, new Identifier(AccessModifier.Section, tableId, columnName)) | ||
438 | { | ||
439 | TableRef = tableId, | ||
440 | Name = columnName, | ||
441 | Type = columnType.Value, | ||
442 | Attributes = attributes, | ||
443 | Width = width, | ||
444 | Category = category, | ||
445 | Description = description, | ||
446 | KeyColumn = keyColumn, | ||
447 | KeyTable = keyTable, | ||
448 | MaxValue = maxValue, | ||
449 | MinValue = minValue, | ||
450 | Modularize = modularization, | ||
451 | Set = setValues, | ||
452 | }); | ||
453 | return column; | ||
454 | } | ||
455 | |||
456 | /// <summary> | ||
457 | /// Parses a Row element. | ||
458 | /// </summary> | ||
459 | /// <param name="node">Element to parse.</param> | ||
460 | /// <param name="sourceLineNumbers">Element's SourceLineNumbers.</param> | ||
461 | /// <param name="tableId">Table Id.</param> | ||
462 | private void ParseRowElement(XElement node, SourceLineNumber sourceLineNumbers, string tableId) | ||
463 | { | ||
464 | var rowId = Guid.NewGuid().ToString("N").ToUpperInvariant(); | ||
465 | |||
466 | foreach (var attrib in node.Attributes()) | ||
467 | { | ||
468 | this.Core.ParseExtensionAttribute(node, attrib); | ||
469 | } | ||
470 | |||
471 | foreach (var child in node.Elements()) | ||
472 | { | ||
473 | var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
474 | switch (child.Name.LocalName) | ||
475 | { | ||
476 | case "Data": | ||
477 | string columnName = null; | ||
478 | string data = null; | ||
479 | foreach (var attrib in child.Attributes()) | ||
480 | { | ||
481 | switch (attrib.Name.LocalName) | ||
482 | { | ||
483 | case "Column": | ||
484 | columnName = this.Core.GetAttributeValue(childSourceLineNumbers, attrib); | ||
485 | break; | ||
486 | case "Value": | ||
487 | data = this.Core.GetAttributeValue(childSourceLineNumbers, attrib); | ||
488 | break; | ||
489 | default: | ||
490 | this.Core.ParseExtensionAttribute(child, attrib); | ||
491 | break; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | this.Core.InnerTextDisallowed(node); | ||
496 | |||
497 | if (null == columnName) | ||
498 | { | ||
499 | this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Column")); | ||
500 | } | ||
501 | |||
502 | if (!this.Core.EncounteredError) | ||
503 | { | ||
504 | this.Core.AddSymbol(new WixCustomTableCellSymbol(childSourceLineNumbers, new Identifier(AccessModifier.Section, tableId, rowId, columnName)) | ||
505 | { | ||
506 | RowId = rowId, | ||
507 | ColumnRef = columnName, | ||
508 | TableRef = tableId, | ||
509 | Data = data | ||
510 | }); | ||
511 | } | ||
512 | break; | ||
513 | default: | ||
514 | this.Core.UnexpectedElement(node, child); | ||
515 | break; | ||
516 | } | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | } | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs index e94114bb..11dc9240 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs | |||
@@ -335,6 +335,38 @@ namespace WixToolsetTest.CoreIntegration | |||
335 | } | 335 | } |
336 | 336 | ||
337 | [Fact] | 337 | [Fact] |
338 | public void CanBuildMsiWithEmptyCustomTableBecauseOfCustomTableRef() | ||
339 | { | ||
340 | var folder = TestData.Get(@"TestData"); | ||
341 | var extensionPath = Path.GetFullPath(new Uri(typeof(ExampleExtensionFactory).Assembly.CodeBase).LocalPath); | ||
342 | |||
343 | using (var fs = new DisposableFileSystem()) | ||
344 | { | ||
345 | var baseFolder = fs.GetFolder(); | ||
346 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
347 | var msiPath = Path.Combine(baseFolder, @"bin\test.msi"); | ||
348 | |||
349 | var result = WixRunner.Execute(new[] | ||
350 | { | ||
351 | "build", | ||
352 | Path.Combine(folder, "EnsureTable", "EnsureCustomTable.wxs"), | ||
353 | Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"), | ||
354 | Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), | ||
355 | "-ext", extensionPath, | ||
356 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
357 | "-intermediateFolder", intermediateFolder, | ||
358 | "-o", msiPath | ||
359 | }); | ||
360 | |||
361 | result.AssertSuccess(); | ||
362 | |||
363 | Assert.True(File.Exists(msiPath)); | ||
364 | var results = Query.QueryDatabaseByTable(msiPath, new[] { "SomeCustomTable" }); | ||
365 | WixAssert.StringCollectionEmpty(results["SomeCustomTable"]); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | [Fact] | ||
338 | public void CanBuildMsiWithEmptyStandardTableBecauseOfEnsureTable() | 370 | public void CanBuildMsiWithEmptyStandardTableBecauseOfEnsureTable() |
339 | { | 371 | { |
340 | var folder = TestData.Get(@"TestData"); | 372 | var folder = TestData.Get(@"TestData"); |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/EnsureTable/EnsureCustomTable.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/EnsureTable/EnsureCustomTable.wxs new file mode 100644 index 00000000..36151cf5 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/EnsureTable/EnsureCustomTable.wxs | |||
@@ -0,0 +1,16 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents"> | ||
5 | <ComponentGroupRef Id="MinimalComponentGroup" /> | ||
6 | </ComponentGroup> | ||
7 | |||
8 | <CustomTableRef Id="SomeCustomTable" /> | ||
9 | </Fragment> | ||
10 | |||
11 | <Fragment> | ||
12 | <CustomTable Id="SomeCustomTable"> | ||
13 | <Column Id="SomeRow" Type="string" Width="72" PrimaryKey="yes" Category="identifier" /> | ||
14 | </CustomTable> | ||
15 | </Fragment> | ||
16 | </Wix> | ||