예제 #1
0
        public void TestBalanceSkip()
        {
            // skip
            JavaCodeParser parser1 = new JavaCodeParser("simple;D");
            parser1.SkipToIfBalanced(';');
            Assert.AreEqual(';', parser1.Char);
            Assert.AreEqual('D', parser1.Next());

            JavaCodeParser parser2 = new JavaCodeParser("find ( ;semicolon {[ ( ; ) ; ]} ; keep looking ) ;-)");
            parser2.SkipToIfBalanced(';');
            Assert.AreEqual(';', parser2.Char);
            Assert.AreEqual('-', parser2.Next());
            Assert.AreEqual(')', parser2.Next());

            JavaCodeParser parser3 = new JavaCodeParser("nope");
            parser3.SkipToIfBalanced(';');
            Assert.AreEqual('n', parser3.Char);

            JavaCodeParser parser4 = new JavaCodeParser("cannot find (;;;)");
            parser4.SkipToIfBalanced(';');
            Assert.AreEqual('c', parser4.Char);

            JavaCodeParser parser5 = new JavaCodeParser("( invalid [ balance ) ] ;");
            parser5.SkipToIfBalanced(';');
            Assert.AreEqual('(', parser5.Char);

            // read
            JavaCodeParser parser6 = new JavaCodeParser("these (are) contents; abc");
            JavaCodeParser readBlock6 = parser6.ReadToIfBalanced(';');
            Assert.AreEqual("these (are) contents", readBlock6.Contents);
            Assert.AreEqual(';', parser6.Char);

            JavaCodeParser parser7 = new JavaCodeParser("cannot find");
            Assert.AreEqual(string.Empty, parser7.ReadToIfBalanced(';').Contents);
        }
예제 #2
0
        public void TestAnnotations()
        {
            Annotation? annotation1 = new JavaCodeParser("@SimpleAnnotation").ReadAnnotation();
            Assert.IsTrue(annotation1.HasValue);
            Assert.AreEqual("SimpleAnnotation", annotation1.Value.SimpleName);

            Annotation? annotation2 = new JavaCodeParser("@ AnnotationWithSpace ").ReadAnnotation();
            Assert.IsTrue(annotation2.HasValue);
            Assert.AreEqual("AnnotationWithSpace", annotation2.Value.SimpleName);

            Annotation? annotation3 = new JavaCodeParser("@full.name.Annotation").ReadAnnotation();
            Assert.IsTrue(annotation3.HasValue);
            Assert.AreEqual("Annotation", annotation3.Value.SimpleName);

            Annotation? annotation4 = new JavaCodeParser("@AnnotationWithArguments(var = true, other = 15)").ReadAnnotation();
            Assert.IsTrue(annotation4.HasValue);
            Assert.AreEqual("AnnotationWithArguments", annotation4.Value.SimpleName);

            Annotation? annotation5 = new JavaCodeParser("@  all.Combined (var = '') ").ReadAnnotation();
            Assert.IsTrue(annotation5.HasValue);
            Assert.AreEqual("Combined", annotation5.Value.SimpleName);

            Annotation? annotation6 = new JavaCodeParser("Invalid").ReadAnnotation();
            Assert.IsFalse(annotation6.HasValue);

            Annotation? annotation7 = new JavaCodeParser("@").ReadAnnotation();
            Assert.IsFalse(annotation7.HasValue);

            Annotation? annotation8 = new JavaCodeParser("@123").ReadAnnotation();
            Assert.IsFalse(annotation8.HasValue);
        }
예제 #3
0
        private static void ReadPackage(JavaCodeParser parser, JavaFileInfo info)
        {
            parser.SkipSpaces();
            parser.SkipReadAnnotationList();
            parser.SkipSpaces();

            info.Package = parser.ReadPackageDeclaration();
        }
예제 #4
0
        private static void ReadImportList(JavaCodeParser parser, JavaFileInfo info)
        {
            while (true)
            {
                parser.SkipSpaces();

                Import?import = parser.ReadImportDeclaration();
                if (!import.HasValue)
                {
                    break;
                }

                info.Imports.Add(import.Value);
            }
        }
예제 #5
0
        public JavaFileInfo Process(File file)
        {
            JavaFileInfo info = new JavaFileInfo();
            fileInfo.Add(file, info);

            JavaCodeParser parser = new JavaCodeParser(JavaParseUtils.PrepareCodeFile(file.Contents));
            parser.AnnotationCallback += IncrementAnnotation;
            parser.CodeBlockCallback += blockParser => ReadCodeBlock(blockParser, GlobalInfo);

            ReadPackage(parser, info);
            ReadImportList(parser, info);
            ReadTopLevelTypes(parser, info);

            UpdateLocalData(info);

            return info;
        }
예제 #6
0
        public JavaFileInfo Process(File file)
        {
            JavaFileInfo info = new JavaFileInfo();

            fileInfo.Add(file, info);

            JavaCodeParser parser = new JavaCodeParser(JavaParseUtils.PrepareCodeFile(file.Contents));

            parser.AnnotationCallback += IncrementAnnotation;
            parser.CodeBlockCallback  += blockParser => ReadCodeBlock(blockParser, GlobalInfo);

            ReadPackage(parser, info);
            ReadImportList(parser, info);
            ReadTopLevelTypes(parser, info);

            UpdateLocalData(info);

            return(info);
        }
예제 #7
0
        private static void ReadTopLevelTypes(JavaCodeParser parser, JavaFileInfo info)
        {
            while (true)
            {
                parser.SkipSpaces();
                if (parser.IsEOF)
                {
                    break;
                }

                Type type = parser.ReadType();

                if (type != null)
                {
                    info.Types.Add(type);
                }
                else
                {
                    break;
                }
            }
        }
예제 #8
0
        private static void ReadCodeBlock(JavaCodeBlockParser blockParser, JavaGlobalInfo info)
        {
            string keyword;

            while((keyword = blockParser.ReadNextKeywordSkip()).Length > 0){
                switch(keyword){
                    case "do":
                        ReadCodeBlock((JavaCodeBlockParser)blockParser.ReadBlock('{', '}'), info);

                        if (blockParser.ReadNextKeywordSkip() != "while"){
                            blockParser.RevertKeywordSkip(); // should not happen
                        }

                        ++info.Statements[FlowStatement.DoWhile];
                        break;

                    case "while":
                        ++info.Statements[FlowStatement.While];
                        break;

                    case "for":
                        JavaCodeBlockParser cycleDeclBlock = (JavaCodeBlockParser)blockParser.ReadBlock('(', ')');
                        ReadCodeBlock(cycleDeclBlock, info);

                        JavaCodeParser cycleDeclParser = new JavaCodeParser(cycleDeclBlock.Contents);
                        cycleDeclParser.ReadTypeOf(false);
                        cycleDeclParser.SkipSpaces().ReadIdentifier();

                        ++info.Statements[cycleDeclParser.SkipSpaces().Char == ':' ? FlowStatement.EnhancedFor : FlowStatement.For];
                        break;

                    case "switch":
                        JavaCodeBlockParser switchBlock = (JavaCodeBlockParser)blockParser.ReadBlock('{', '}');
                        ReadCodeBlock(switchBlock, info);

                        switchBlock.Reset();
                        string switchKeyword;
                        int cases = 0;

                        while((switchKeyword = switchBlock.ReadNextKeywordSkip()).Length > 0){
                            if (switchKeyword == "switch"){
                                switchBlock.SkipBlock('{', '}');
                            }
                            else if (switchKeyword == "case"){
                                ++info.Statements[FlowStatement.SwitchCase];
                                ++cases;
                            }
                            else if (switchKeyword == "default"){
                                ++info.Statements[FlowStatement.SwitchDefault]; // TODO count as a case?
                            }
                        }

                        if (cases < info.MinSwitchCases)info.MinSwitchCases = cases;
                        if (cases > info.MaxSwitchCases)info.MaxSwitchCases = cases;

                        ++info.Statements[FlowStatement.Switch];
                        break;

                    case "try":
                        bool isTryWithResources = blockParser.SkipSpaces().Char == '(';

                        ReadCodeBlock((JavaCodeBlockParser)blockParser.ReadBlock('{', '}'), info);

                        string tryKeyword;
                        int catches = 0;

                        while((tryKeyword = blockParser.ReadNextKeywordSkip()).Length > 0){
                            if (tryKeyword == "catch"){
                                ++info.Statements[FlowStatement.Catch];
                                ++catches;
                            }
                            else if (tryKeyword == "finally"){
                                ++info.Statements[FlowStatement.Finally];

                                if (isTryWithResources)++info.TryWithResourcesWithFinally;
                                else ++info.TryCatchWithFinally;
                            }
                            else if (tryKeyword != "try"){
                                blockParser.RevertKeywordSkip();
                                break;
                            }

                            ReadCodeBlock((JavaCodeBlockParser)blockParser.ReadBlock('{', '}'), info);
                        }

                        if (catches < info.MinCatchBlocks)info.MinCatchBlocks = catches;
                        if (catches > info.MaxCatchBlocks)info.MaxCatchBlocks = catches;

                        ++info.Statements[isTryWithResources ? FlowStatement.TryWithResources : FlowStatement.TryCatch];
                        ++info.Statements[FlowStatement.Try];
                        break;

                    case "if":
                        ++info.Statements[FlowStatement.If];
                        break;

                    case "else":
                        ++info.Statements[FlowStatement.Else];

                        if (blockParser.ReadNextKeywordSkip() != "if"){
                            blockParser.RevertKeywordSkip();
                        }

                        break;

                    case "return":
                        ++info.Statements[FlowStatement.Return];
                        break;

                    case "continue":
                        ++info.Statements[FlowStatement.Continue];
                        break;

                    case "break":
                        ++info.Statements[FlowStatement.Break];
                        break;
                }
            }
        }
예제 #9
0
        private static void ReadTopLevelTypes(JavaCodeParser parser, JavaFileInfo info)
        {
            while(true){
                parser.SkipSpaces();
                if (parser.IsEOF)break;

                Type type = parser.ReadType();

                if (type != null)info.Types.Add(type);
                else break;
            }
        }
예제 #10
0
        private static void ReadPackage(JavaCodeParser parser, JavaFileInfo info)
        {
            parser.SkipSpaces();
            parser.SkipReadAnnotationList();
            parser.SkipSpaces();

            info.Package = parser.ReadPackageDeclaration();
        }
예제 #11
0
        private static void ReadImportList(JavaCodeParser parser, JavaFileInfo info)
        {
            while(true){
                parser.SkipSpaces();

                Import? import = parser.ReadImportDeclaration();
                if (!import.HasValue)break;

                info.Imports.Add(import.Value);
            }
        }
예제 #12
0
        private static void ReadCodeBlock(JavaCodeBlockParser blockParser, JavaGlobalInfo info)
        {
            string keyword;

            while ((keyword = blockParser.ReadNextKeywordSkip()).Length > 0)
            {
                switch (keyword)
                {
                case "do":
                    ReadCodeBlock((JavaCodeBlockParser)blockParser.ReadBlock('{', '}'), info);

                    if (blockParser.ReadNextKeywordSkip() != "while")
                    {
                        blockParser.RevertKeywordSkip();     // should not happen
                    }

                    ++info.Statements[FlowStatement.DoWhile];
                    break;

                case "while":
                    ++info.Statements[FlowStatement.While];
                    break;

                case "for":
                    JavaCodeBlockParser cycleDeclBlock = (JavaCodeBlockParser)blockParser.ReadBlock('(', ')');
                    ReadCodeBlock(cycleDeclBlock, info);

                    JavaCodeParser cycleDeclParser = new JavaCodeParser(cycleDeclBlock.Contents);
                    cycleDeclParser.ReadTypeOf(false);
                    cycleDeclParser.SkipSpaces().ReadIdentifier();

                    ++info.Statements[cycleDeclParser.SkipSpaces().Char == ':' ? FlowStatement.EnhancedFor : FlowStatement.For];
                    break;

                case "switch":
                    JavaCodeBlockParser switchBlock = (JavaCodeBlockParser)blockParser.ReadBlock('{', '}');
                    ReadCodeBlock(switchBlock, info);

                    switchBlock.Reset();
                    string switchKeyword;
                    int    cases = 0;

                    while ((switchKeyword = switchBlock.ReadNextKeywordSkip()).Length > 0)
                    {
                        if (switchKeyword == "switch")
                        {
                            switchBlock.SkipBlock('{', '}');
                        }
                        else if (switchKeyword == "case")
                        {
                            ++info.Statements[FlowStatement.SwitchCase];
                            ++cases;
                        }
                        else if (switchKeyword == "default")
                        {
                            ++info.Statements[FlowStatement.SwitchDefault];     // TODO count as a case?
                        }
                    }

                    if (cases < info.MinSwitchCases)
                    {
                        info.MinSwitchCases = cases;
                    }
                    if (cases > info.MaxSwitchCases)
                    {
                        info.MaxSwitchCases = cases;
                    }

                    ++info.Statements[FlowStatement.Switch];
                    break;

                case "try":
                    bool isTryWithResources = blockParser.SkipSpaces().Char == '(';

                    ReadCodeBlock((JavaCodeBlockParser)blockParser.ReadBlock('{', '}'), info);

                    string tryKeyword;
                    int    catches = 0;

                    while ((tryKeyword = blockParser.ReadNextKeywordSkip()).Length > 0)
                    {
                        if (tryKeyword == "catch")
                        {
                            ++info.Statements[FlowStatement.Catch];
                            ++catches;
                        }
                        else if (tryKeyword == "finally")
                        {
                            ++info.Statements[FlowStatement.Finally];

                            if (isTryWithResources)
                            {
                                ++info.TryWithResourcesWithFinally;
                            }
                            else
                            {
                                ++info.TryCatchWithFinally;
                            }
                        }
                        else if (tryKeyword != "try")
                        {
                            blockParser.RevertKeywordSkip();
                            break;
                        }

                        ReadCodeBlock((JavaCodeBlockParser)blockParser.ReadBlock('{', '}'), info);
                    }

                    if (catches < info.MinCatchBlocks)
                    {
                        info.MinCatchBlocks = catches;
                    }
                    if (catches > info.MaxCatchBlocks)
                    {
                        info.MaxCatchBlocks = catches;
                    }

                    ++info.Statements[isTryWithResources ? FlowStatement.TryWithResources : FlowStatement.TryCatch];
                    ++info.Statements[FlowStatement.Try];
                    break;

                case "if":
                    ++info.Statements[FlowStatement.If];
                    break;

                case "else":
                    ++info.Statements[FlowStatement.Else];

                    if (blockParser.ReadNextKeywordSkip() != "if")
                    {
                        blockParser.RevertKeywordSkip();
                    }

                    break;

                case "return":
                    ++info.Statements[FlowStatement.Return];
                    break;

                case "continue":
                    ++info.Statements[FlowStatement.Continue];
                    break;

                case "break":
                    ++info.Statements[FlowStatement.Break];
                    break;
                }
            }
        }
예제 #13
0
        /// <summary>
        /// Recursively reads all members of a Type, including all nested Types. Called on a cloned JavaCodeParser that only
        /// contains contents of the Type block.
        /// </summary>
        private void ReadTypeContents(Type type)
        {
            // enum values
            if (type.Declaration == Type.DeclarationType.Enum){
                Type.DataEnum enumData = type.GetData<Type.DataEnum>();

                JavaCodeParser enumParser = ReadToIfBalanced(';');
                if (enumParser.Contents.Length == 0)enumParser = this;

                foreach(string enumValue in enumParser.ReadEnumValueList()){
                    enumData.EnumValues.Add(enumValue);
                }

                if (Char == ';')Skip();
            }

            // members
            int skippedMembers = 0;

            while(!IsEOF && skippedMembers < 50){
                Member memberInfo = SkipReadMemberInfo(); // skips spaces at the beginning and end

                // nested types
                Type.DeclarationType? declaration = ReadTypeDeclaration();

                if (declaration.HasValue){
                    string identifier = SkipSpaces().ReadIdentifier();
                    if (identifier.Length == 0)break; // error, break out

                    Type nestedType = new Type(declaration.Value, identifier, memberInfo);
                    ((JavaCodeParser)SkipTo('{').ReadBlock('{', '}')).ReadTypeContents(nestedType);

                    SkipSpacesAndSemicolons();

                    type.NestedTypes.Add(nestedType);
                    continue;
                }

                // static / instance initializer
                if (Char == '{'){
                    Method method = new Method(memberInfo.Modifiers.HasFlag(Modifiers.Static) ? "<clinit>" : "<init>", TypeOf.Void(), memberInfo);
                    SkipProcessCodeBlock();

                    type.GetData().Methods.Add(method);
                    continue;
                }

                // fields and methods
                TypeOf? returnOrFieldType = ReadTypeOf(false);

                if (returnOrFieldType.HasValue){
                    int prevCursor = cursor;
                    string identifier = SkipSpaces().ReadIdentifier();

                    if (identifier.Length == 0 && string.Equals(returnOrFieldType.Value.AsSimpleType(), type.Identifier)){ // constructor
                        identifier = Method.ConstructorIdentifier;
                        returnOrFieldType = TypeOf.Void();
                    }

                    if (identifier.Length == 0)break; // error, break out

                    if (SkipSpaces().Char == '('){ // method
                        List<TypeOf> parameterList = ((JavaCodeParser)ReadBlock('(', ')')).ReadMethodParameterList();

                        if (type.Declaration == Type.DeclarationType.Annotation){
                            if (SkipSpaces().SkipIfMatch("default^n")){
                                memberInfo = new Member(memberInfo, memberInfo.Modifiers | Modifiers.Default);
                                SkipTo(';');
                            }
                        }
                        else{
                            if (SkipSpaces().SkipIfMatch("throws^s")){
                                while(true){
                                    ReadFullTypeName();

                                    if (SkipSpaces().Char == ',')Skip().SkipSpaces();
                                    else break;
                                }
                            }
                        }

                        if (Char == ';')Skip();
                        else{
                            SkipProcessCodeBlock();
                            SkipSpacesAndSemicolons();
                        }

                        type.GetData().Methods.Add(new Method(identifier, returnOrFieldType.Value, parameterList, type.GetData().UpdateMethodInfo(memberInfo)));
                    }
                    else{ // field
                        Type.TypeData data = type.GetData();
                        cursor = prevCursor;

                        foreach(string fieldIdentifier in ReadToIfBalanced(';').ReadFieldIdentifierList()){
                            data.Fields.Add(new Field(fieldIdentifier, returnOrFieldType.Value, data.UpdateFieldInfo(memberInfo)));
                        }

                        Skip();
                    }

                    continue;
                }

                // extra checks before the skip
                if (Char == ';'){
                    Skip();
                    continue;
                }

                if (IsEOF)break;

                // skip
                if (skippedMembers == 0){
                    System.Diagnostics.Debugger.Break();
                }

                SkipBlock('{', '}');
                SkipSpacesAndSemicolons();
                ++skippedMembers;
            }
        }