예제 #1
0
        private List <LogInfo> ValidateUISection(ScriptSection section)
        {
            // Force parsing of code, bypassing caching by section.GetUICtrls()
            List <string>    lines   = section.GetLines();
            SectionAddress   addr    = new SectionAddress(p, section);
            List <UIControl> uiCtrls = UIParser.ParseRawLines(lines, addr, out List <LogInfo> logs);

            foreach (UIControl uiCmd in uiCtrls)
            {
                switch (uiCmd.Type)
                {
                case UIControlType.CheckBox:
                {
                    Debug.Assert(uiCmd.Info.GetType() == typeof(UIInfo_CheckBox));
                    UIInfo_CheckBox info = uiCmd.Info as UIInfo_CheckBox;

                    if (info.SectionName != null)
                    {
                        if (p.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName]));
                        }
                    }
                }
                break;

                case UIControlType.Button:
                {
                    Debug.Assert(uiCmd.Info.GetType() == typeof(UIInfo_Button));
                    UIInfo_Button info = uiCmd.Info as UIInfo_Button;

                    if (info.SectionName != null)
                    {
                        if (p.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName]));
                        }
                    }
                }
                break;

                case UIControlType.RadioButton:
                {
                    Debug.Assert(uiCmd.Info.GetType() == typeof(UIInfo_RadioButton));
                    UIInfo_RadioButton info = uiCmd.Info as UIInfo_RadioButton;

                    if (info.SectionName != null)
                    {
                        if (p.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName]));
                        }
                    }
                }
                break;
                }
            }

            return(logs);
        }
예제 #2
0
        public static UICommand ParseUICommand(List <string> rawLines, SectionAddress addr, ref int idx)
        {
            UIType type    = UIType.None;
            string rawLine = rawLines[idx].Trim();

            // Check if rawCode is Empty
            if (rawLine.Equals(string.Empty))
            {
                return(new UICommand(rawLine, addr, string.Empty));
            }

            // Comment Format : starts with '//' or '#', ';'
            if (rawLine.StartsWith("//") || rawLine.StartsWith("#") || rawLine.StartsWith(";"))
            {
                return(new UICommand(rawLine, addr, string.Empty));
            }

            // Find key of interface control
            string key      = string.Empty;
            string rawValue = string.Empty;
            int    equalIdx = rawLine.IndexOf('=');

            if (equalIdx != -1)
            {
                key      = rawLine.Substring(0, equalIdx);
                rawValue = rawLine.Substring(equalIdx + 1);
            }
            else
            {
                throw new InvalidCommandException($"Interface control [{rawValue}] does not have name", rawLine);
            }

            // Parse Arguments
            List <string> args = new List <string>();

            try
            {
                string remainder = rawValue;
                while (remainder != null)
                {
                    Tuple <string, string> tuple = CodeParser.GetNextArgument(remainder);
                    args.Add(tuple.Item1);
                    remainder = tuple.Item2;
                }
            }
            catch (InvalidCommandException e) { throw new InvalidCommandException(e.Message, rawLine); }

            // Check doublequote's occurence - must be 2n
            if (StringHelper.CountOccurrences(rawValue, "\"") % 2 == 1)
            {
                throw new InvalidCommandException($"Interface control [{rawValue}]'s doublequotes mismatch", rawLine);
            }

            // Check if last operand is \ - MultiLine check - only if one or more operands exists
            if (0 < args.Count)
            {
                while (args.Last().Equals(@"\", StringComparison.OrdinalIgnoreCase))
                {                              // Split next line and append to List<string> operands
                    if (rawLines.Count <= idx) // Section ended with \, invalid grammar!
                    {
                        throw new InvalidCommandException($@"Last interface control [{rawValue}] cannot end with '\' ", rawLine);
                    }
                    idx++;
                    args.AddRange(rawLines[idx].Trim().Split(','));
                }
            }

            // UICommand should have at least 7 operands
            //    Text, Visibility, Type, X, Y, width, height, [Optional]
            if (args.Count < 7)
            {
                throw new InvalidCommandException($"Interface control [{rawValue}] must have at least 7 arguments", rawLine);
            }

            // Parse opcode
            try { type = UIParser.ParseControlType(args[2]); }
            catch (InvalidCommandException e) { throw new InvalidCommandException(e.Message, rawLine); }

            // Remove UIControlType from operands
            //   Leftover : Text, Visibility, X, Y, width, height, [Optional]
            args.RemoveAt(2);

            // Forge UICommand
            string text       = StringEscaper.Unescape(args[0]);
            bool   visibility = string.Equals(args[1], "1", StringComparison.Ordinal);

            NumberHelper.ParseInt32(args[2], out int x);
            NumberHelper.ParseInt32(args[3], out int y);
            NumberHelper.ParseInt32(args[4], out int width);
            NumberHelper.ParseInt32(args[5], out int height);
            Rect   rect = new Rect(x, y, width, height);
            UIInfo info;

            try { info = ParseUICommandInfo(type, args); }
            catch (InvalidCommandException e) { throw new InvalidCommandException(e.Message, rawLine); }
            return(new UICommand(rawLine, addr, key, text, visibility, type, rect, info));
        }
예제 #3
0
        private List <LogInfo> CheckInterfaceSection(ScriptSection section, string rawLine = null, int lineIdx = 0)
        {
            // If this section was already visited, return.
            if (_visitedSections.Contains(section.Name))
            {
                return(new List <LogInfo>());
            }
            _visitedSections.Add(section.Name);

            // Force parsing of code, bypassing caching by section.GetUICtrls()
            string[] lines = section.Lines;
            if (lines == null)
            {
                string msg = $"Section [{section.Name}] is not a valid interface section";
                if (rawLine != null)
                {
                    msg += $" ({rawLine})";
                }
                if (0 < lineIdx)
                {
                    msg += $" (Line {lineIdx})";
                }

                return(new List <LogInfo> {
                    new LogInfo(LogState.Error, msg)
                });
            }

            (List <UIControl> uiCtrls, List <LogInfo> logs) = UIParser.ParseStatements(lines, section);
            foreach (UIControl uiCtrl in uiCtrls)
            {
                switch (uiCtrl.Type)
                {
                case UIControlType.CheckBox:
                {
                    UIInfo_CheckBox info = uiCtrl.Info.Cast <UIInfo_CheckBox>();

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(CheckCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.ComboBox:
                {
                    UIInfo_ComboBox info = uiCtrl.Info.Cast <UIInfo_ComboBox>();

                    // Practically, this means info.Index is -1 -> uiCtrl.Text not being one of info.Items
                    if (info.Index < 0 || info.Items.Count <= info.Index)
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Incorrect selected value [{uiCtrl.Text}]", uiCtrl));
                    }
                }
                break;

                case UIControlType.Image:
                {
                    // Check encoded image
                    string imageSection = StringEscaper.Unescape(uiCtrl.Text);
                    if (!imageSection.Equals(UIInfo_Image.NoResource, StringComparison.OrdinalIgnoreCase) &&
                        !EncodedFile.ContainsInterface(_sc, imageSection))
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Image resource [{imageSection}] does not exist", uiCtrl));
                    }

                    UIInfo_Image info = uiCtrl.Info.Cast <UIInfo_Image>();

                    // Check if image control have empty or invalid url.
                    // Ex) Colors_Image=ThemeColors.jpg,1,5,11,228,260,80,
                    if (info.Url != null)
                    {
                        string url = StringEscaper.Unescape(info.Url);
                        if (!StringEscaper.IsUrlValid(url))
                        {
                            if (url.IndexOf("://", StringComparison.Ordinal) != -1)
                            {
                                logs.Add(new LogInfo(LogState.Warning, $"Incorrect URL [{url}]", uiCtrl));
                            }
                            else
                            {
                                logs.Add(new LogInfo(LogState.Warning, "URL does not have a scheme. Did you omit \"http(s)://\"?", uiCtrl));
                            }
                        }
                    }
                }
                break;

                case UIControlType.TextFile:
                {
                    string textSection = StringEscaper.Unescape(uiCtrl.Text);
                    if (!textSection.Equals(UIInfo_TextFile.NoResource, StringComparison.OrdinalIgnoreCase) &&
                        !EncodedFile.ContainsInterface(_sc, textSection))
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Text resource [{textSection}] does not exist", uiCtrl));
                    }
                }
                break;

                case UIControlType.Button:
                {
                    UIInfo_Button info = uiCtrl.Info.Cast <UIInfo_Button>();

                    string pictureSection = info.Picture;
                    if (pictureSection != null &&
                        !pictureSection.Equals(UIInfo_Button.NoPicture, StringComparison.OrdinalIgnoreCase) &&
                        !EncodedFile.ContainsInterface(_sc, pictureSection))
                    {
                        if (pictureSection.Length == 0)         // Due to quirks of WinBuilder's editor, many buttons have '' instead of '0' in the place of <Picture>.
                        {
                            logs.Add(new LogInfo(LogState.Warning, "Image resource entry is empty. Use [0] to represent not having an image resource.", uiCtrl));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Warning, $"Image resource [{pictureSection}] does not exist", uiCtrl));
                        }
                    }

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(CheckCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.WebLabel:
                {
                    UIInfo_WebLabel info = uiCtrl.Info.Cast <UIInfo_WebLabel>();

                    // Sometime developers forget to put proper scheme in WebLabel's url.
                    // Ex) PStart_WebLabel="PStart Homepage",1,10,668,122,98,18,www.pegtop.de/start/
                    string url = StringEscaper.Unescape(info.Url);
                    if (!StringEscaper.IsUrlValid(url))
                    {
                        if (url.IndexOf("://", StringComparison.Ordinal) != -1)
                        {
                            logs.Add(new LogInfo(LogState.Warning, $"Incorrect URL [{url}]", uiCtrl));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Warning, "URL does not have scheme. Did you omit \"http(s)://\"?", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.RadioButton:
                {
                    UIInfo_RadioButton info = uiCtrl.Info.Cast <UIInfo_RadioButton>();

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(CheckCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.FileBox:
                {
                    UIInfo_FileBox info = uiCtrl.Info.Cast <UIInfo_FileBox>();

                    if (info.IsFile)
                    {         // Select File
                        if (info.Filter != null)
                        {
                            string filter = StringEscaper.Unescape(info.Filter);
                            if (StringEscaper.IsFileFilterValid(filter) == false)
                            {
                                logs.Add(new LogInfo(LogState.Warning, $"File filter pattern [{filter}] is invalid", uiCtrl));
                            }
                        }
                    }
                    else
                    {         // Select Folder
                        if (info.Filter != null)
                        {
                            logs.Add(new LogInfo(LogState.Warning, $"File filters cannot be used for folder selection", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.RadioGroup:
                {
                    UIInfo_RadioGroup info = uiCtrl.Info.Cast <UIInfo_RadioGroup>();

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(CheckCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }

                    // Practically, this means info.Index is -1 -> uiCtrl.Text not being one of info.Items
                    if (info.Selected < 0 || info.Items.Count <= info.Selected)
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Incorrect selected index [{info.Selected}]", uiCtrl));
                    }
                }
                break;
                }
            }
            return(logs);
        }
예제 #4
0
        public static UIControl ParseUIControl(IList <string> rawLines, ScriptSection section, ref int idx)
        {
            // UICommand's line number in physical file
            int lineIdx = section.LineIdx + 1 + idx;

            // Get rawLine
            string rawLine = rawLines[idx].Trim();

            // Check if rawLine is empty
            if (rawLine.Length == 0)
            {
                return(null);
            }

            // Line Comment Identifier : '//', '#', ';'
            if (rawLine.StartsWith("//", StringComparison.Ordinal) || rawLine[0] == '#' || rawLine[0] == ';')
            {
                return(null);
            }

            // Find key of interface control
            string key;
            string rawValue = string.Empty;
            int    equalIdx = rawLine.IndexOf('=');

            if (equalIdx != -1 && equalIdx != 0)
            {
                key      = rawLine.Substring(0, equalIdx);
                rawValue = rawLine.Substring(equalIdx + 1);
            }
            else
            {
                throw new InvalidCommandException($"Interface control [{rawValue}] must have a key", rawLine);
            }

            // Parse Arguments
            List <string> args = new List <string>();

            try
            {
                string remainder = rawValue;
                while (remainder != null)
                {
                    string next;
                    (next, remainder) = CodeParser.GetNextArgument(remainder);
                    args.Add(next);
                }
            }
            catch (InvalidCommandException e) { throw new InvalidCommandException(e.Message, rawLine); }

            // Check double-quote's occurence - must be 2n
            if (StringHelper.CountSubStr(rawValue, "\"") % 2 == 1)
            {
                throw new InvalidCommandException("Double-quote's number should be even", rawLine);
            }

            // Check if last operand is \ - MultiLine check - only if one or more operands exists
            if (0 < args.Count)
            {
                while (args.Last().Equals(@"\", StringComparison.OrdinalIgnoreCase))
                {                              // Split next line and append to List<string> operands
                    if (rawLines.Count <= idx) // Section ended with \, invalid grammar!
                    {
                        throw new InvalidCommandException(@"Last interface control cannot end with '\'", rawLine);
                    }
                    idx++;
                    args.AddRange(rawLines[idx].Trim().Split(','));
                }
            }

            // UIControl should have at least 7 operands
            //    Text, Visibility, Type, X, Y, width, height, [Optional]
            if (args.Count < 7)
            {
                throw new InvalidCommandException($"Interface control [{rawValue}] must have at least 7 arguments", rawLine);
            }

            // Parse UIControlType
            UIControlType type;

            try { type = UIParser.ParseControlTypeVal(args[2]); }
            catch (InvalidCommandException e) { throw new InvalidCommandException(e.Message, rawLine); }

            // Remove UIControlType from operands
            //   Leftover : Text, Visibility, X, Y, width, height, [Optional]
            args.RemoveAt(2);

            // Forge UIControl
            string text          = args[0];
            string visibilityStr = args[1];
            bool   visibility;

            if (visibilityStr.Equals("1", StringComparison.Ordinal) ||
                visibilityStr.Equals("True", StringComparison.OrdinalIgnoreCase))
            {
                visibility = true;
            }
            else if (visibilityStr.Equals("0", StringComparison.Ordinal) ||
                     visibilityStr.Equals("False", StringComparison.OrdinalIgnoreCase))
            {
                visibility = false;
            }
            else
            {
                throw new InvalidCommandException($"Invalid value in [{visibilityStr}]", rawLine);
            }

            bool intParse = true;

            intParse &= NumberHelper.ParseInt32(args[2], out int x);
            intParse &= NumberHelper.ParseInt32(args[3], out int y);
            intParse &= NumberHelper.ParseInt32(args[4], out int width);
            intParse &= NumberHelper.ParseInt32(args[5], out int height);
            if (!intParse)
            {
                throw new InvalidCommandException($"Invalid integers in [{rawValue}]", rawLine);
            }

            UIInfo info;

            try { info = ParseUIControlInfo(type, args); }
            catch (InvalidCommandException e) { throw new InvalidCommandException(e.Message, rawLine); }
            return(new UIControl(rawLine, section, key, text, visibility, type, x, y, width, height, info, lineIdx));
        }
예제 #5
0
        private List <LogInfo> ValidateInterfaceSection(ScriptSection section, string rawLine = null, int lineIdx = 0)
        {
            // Force parsing of code, bypassing caching by section.GetUICtrls()
            string[] lines = section.Lines;
            if (lines == null)
            {
                string msg = $"Section [{section.Name}] is not a valid interface section";
                if (rawLine != null)
                {
                    msg += $" ({rawLine})";
                }
                if (0 < lineIdx)
                {
                    msg += $" (Line {lineIdx})";
                }

                return(new List <LogInfo> {
                    new LogInfo(LogState.Error, msg)
                });
            }

            (List <UIControl> uiCtrls, List <LogInfo> logs) = UIParser.ParseStatements(lines, section);
            foreach (UIControl uiCtrl in uiCtrls)
            {
                switch (uiCtrl.Type)
                {
                case UIControlType.CheckBox:
                {
                    UIInfo_CheckBox info = uiCtrl.Info.Cast <UIInfo_CheckBox>();

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.Image:
                    if (!uiCtrl.Text.Equals(UIInfo_Image.NoResource, StringComparison.OrdinalIgnoreCase) &&
                        !EncodedFile.ContainsInterface(_sc, uiCtrl.Text))
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Image resource [{uiCtrl.Text}] does not exist", uiCtrl));
                    }
                    break;

                case UIControlType.TextFile:
                    if (!uiCtrl.Text.Equals(UIInfo_TextFile.NoResource, StringComparison.OrdinalIgnoreCase) &&
                        !EncodedFile.ContainsInterface(_sc, uiCtrl.Text))
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Text resource [{uiCtrl.Text}] does not exist", uiCtrl));
                    }
                    break;

                case UIControlType.Button:
                {
                    UIInfo_Button info = uiCtrl.Info.Cast <UIInfo_Button>();

                    if (info.Picture != null &&
                        !info.Picture.Equals(UIInfo_Button.NoPicture, StringComparison.OrdinalIgnoreCase) &&
                        !EncodedFile.ContainsInterface(_sc, info.Picture))
                    {
                        logs.Add(new LogInfo(LogState.Warning, $"Image resource [{info.Picture}] does not exist", uiCtrl));
                    }

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.RadioButton:
                {
                    UIInfo_RadioButton info = uiCtrl.Info.Cast <UIInfo_RadioButton>();

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;

                case UIControlType.RadioGroup:
                {
                    UIInfo_RadioGroup info = uiCtrl.Info.Cast <UIInfo_RadioGroup>();

                    if (info.SectionName != null)
                    {
                        if (_sc.Sections.ContainsKey(info.SectionName))         // Only if section exists
                        {
                            logs.AddRange(ValidateCodeSection(_sc.Sections[info.SectionName], uiCtrl.RawLine, uiCtrl.LineIdx));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", uiCtrl));
                        }
                    }
                }
                break;
                }
            }
            return(logs);
        }