All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lv.ctco.scm.gradle.xamarin.SolutionParser.groovy Maven / Gradle / Ivy

Go to download

The C.T.Co Mobile Plugin for Gradle helps you to configure and build Xcode and Xamarin (iOS, Android) apps.

There is a newer version: 0.15.4.1
Show newest version
/*
 * @(#)SolutionParser.groovy
 *
 * Copyright C.T.Co Ltd, 15/25 Jurkalnes Street, Riga LV-1046, Latvia. All rights reserved.
 */

package lv.ctco.scm.gradle.xamarin

import org.codehaus.jparsec.Parser
import org.codehaus.jparsec.Parsers
import org.codehaus.jparsec.Scanners
import org.codehaus.jparsec.functors.Map2
import org.codehaus.jparsec.functors.Pair
import org.codehaus.jparsec.pattern.Pattern
import org.codehaus.jparsec.pattern.Patterns

/**
 *
 * MS Visual Studion solution file parser. This parser is quite simple and is not error-proof in case of
 * manual solution file editing. It implement parsing of only the basic configurations like Project and Global
 * tags.
 *
 * Please have a look a the lv.ctco.scm.mobile.xamarin.SolutionParserTest for more information.
 *
 */

public class SolutionParser {

    protected File file

    public SolutionParser(File file) {
        this.file = file
    }

    /**
     * Parses a solution file.
     *
     * @return Object representation of the parsed solution file.
     */
    Solution parse() {
        if (!file.exists()) {
            throw new IOException("Solution file $file.absolutePath does not exist")
        }
        createSolutionParser().parse(file.text)
    }

    protected static final Parser STRING_PARSER =
            Scanners.DOUBLE_QUOTE_STRING.map(
                    [
                            map: { String str -> str.length() > 2 ? str[1..str.length() - 2] : '' }
                    ] as org.codehaus.jparsec.functors.Map
            )

    protected static Parser createProjectUnitParser() {
        Scanners.string('Project').next(
                Parsers.between(
                        Scanners.isChar('('.toCharacter()),
                        STRING_PARSER,
                        Scanners.isChar(')'.toCharacter()),
                )
        )
    }

    protected static Parser> createCommaSeparatedStringsParser() {
        Parsers.sequence(
                Scanners.WHITESPACES.optional(),
                STRING_PARSER,
        ).sepBy(Scanners.isChar(','.toCharacter()))
    }

    protected static final Parser ASSIGNMENT = Parsers.sequence(
            Scanners.WHITESPACES,
            Scanners.isChar('='.toCharacter()),
            Scanners.WHITESPACES
    )

    protected static Parser createProjectSectionParser() {
        Parsers.sequence(createProjectUnitParser().followedBy(ASSIGNMENT), createCommaSeparatedStringsParser(), [
                map: { String projectType, List values ->
                    new SlnProjectSection(values[0], projectType, values[1], values[2])
                }
        ] as Map2, SlnProjectSection>).
                followedBy(Scanners.WHITESPACES).
                followedBy(Scanners.string('EndProject'))
    }

    protected static Parser> createProjectSectionListParser() {
        Parsers.or(
                createProjectSectionParser().followedBy(Scanners.WHITESPACES),
                (Parser)Parsers.never()
        ).many()
    }

    protected static Parser> createPropertyParser() {
        Pattern pattern = Patterns.regex('[^=&&[^\\r\\n\\f]]+')
        Parser identifierParser = Scanners.pattern(pattern, 'identifier').source().map(
                new org.codehaus.jparsec.functors.Map() {

                    String map(String from) {
                        return from.trim()
                    }
                })
        Parsers.tuple(identifierParser.followedBy(Scanners.isChar('='.toCharacter())), identifierParser)
    }

    protected static Parser createGlobalSectionUnitParser() {
        Parser sectionNameParser = Scanners.pattern(Patterns.regex('[^)]+'), 'section name').source()
        Scanners.string('GlobalSection(').
                next(sectionNameParser).
                followedBy(
                        Parsers.sequence(
                                Scanners.isChar(')'.toCharacter()),
                                Scanners.WHITESPACES,
                                Scanners.isChar('='.toCharacter()),
                                Scanners.WHITESPACES
                        )
                ).followedBy(
                Parsers.or(
                        Scanners.string('preSolution'),
                        Scanners.string('postSolution')
                )
        )
    }

    protected static Parser createGlobalSectionParser() {
        Parser>> propertyListParser =
                Parsers.or(
                        createPropertyParser().followedBy(Scanners.WHITESPACES),
                        Parsers.never() as Parser>
                ).many()
        Parsers.sequence(
                createGlobalSectionUnitParser().followedBy(Scanners.WHITESPACES),
                propertyListParser,
                new Map2>, SlnGlobalSection>() {

                    SlnGlobalSection map(String sectionName, List> properties) {
                        SlnGlobalSection section = new SlnGlobalSection(sectionName)
                        properties.each { Pair property ->
                            section.putProperty(property.a, property.b)
                        }
                        return section
                    }
                }
        ).followedBy(Scanners.string('EndGlobalSection'))
    }

    protected static Parser> createGlobalSectionListParser() {
        Parsers.between(
                Scanners.string('Global').followedBy(Scanners.WHITESPACES),
                Parsers.or(createGlobalSectionParser().followedBy(Scanners.WHITESPACES),
                        (Parser)Parsers.never()).many(),
                Scanners.string('EndGlobal')
        )
    }

    protected static Parser createSolutionParser() {
        Scanners.WHITESPACES.
                followedBy(Scanners.string('Microsoft Visual Studio Solution File, Format Version 12.00')).optional().
                followedBy(Scanners.WHITESPACES).
                followedBy(Scanners.pattern(Patterns.regex('# Visual Studio .*'), 'Visual Studio version')).optional().
                followedBy(Scanners.WHITESPACES).next(Parsers.sequence(
                createProjectSectionListParser(),
                createGlobalSectionListParser(),
                new Map2, List, Solution>() {
                    Solution map(List projectSections, List globalSections) {
                        return new Solution(projectSections, globalSections)
                    }
                }
        )).followedBy(Scanners.WHITESPACES.optional())
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy