"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseProps = exports.parseGradle = void 0;
const good_enough_parser_1 = require("good-enough-parser");
const regex_1 = require("../../../util/regex");
const common_1 = require("./parser/common");
const handlers_1 = require("./parser/handlers");
const utils_1 = require("./utils");
const groovy = good_enough_parser_1.lang.createLang('groovy');
const qStringValue = good_enough_parser_1.query.str((ctx, node) => {
    (0, common_1.storeVarToken)(ctx, node);
    return ctx;
});
const qStringValueAsSymbol = good_enough_parser_1.query.str((ctx, node) => {
    const nodeTransformed = {
        ...node,
        type: 'symbol',
    };
    (0, common_1.storeVarToken)(ctx, nodeTransformed);
    return ctx;
});
// foo.bar["baz"] = "1.2.3"
const qVariableAssignmentIdentifier = good_enough_parser_1.query
    .sym(common_1.storeVarToken)
    .many(good_enough_parser_1.query.alt(good_enough_parser_1.query.op('.').sym(common_1.storeVarToken), good_enough_parser_1.query.tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '[',
    endsWith: ']',
    search: good_enough_parser_1.query.begin().join(qStringValueAsSymbol).end(),
})), 0, 32)
    .handler(common_1.stripReservedPrefixFromKeyTokens);
// foo.bar["baz"] -> "foo.bar.baz"
const qVariableAccessIdentifier = qVariableAssignmentIdentifier.handler(common_1.coalesceVariable);
// project.ext.getProperty(...)
// extra.get(...)
const qPropertyAccessIdentifier = good_enough_parser_1.query
    .opt(good_enough_parser_1.query.sym((0, regex_1.regEx)(/^(?:rootProject|project)$/)).op('.'))
    .alt(good_enough_parser_1.query.opt(good_enough_parser_1.query.sym('ext').op('.')).sym((0, regex_1.regEx)(/^(?:property|getProperty)$/)), good_enough_parser_1.query
    .sym((0, regex_1.regEx)(/^(?:extra|ext)$/))
    .op('.')
    .sym('get'))
    .tree({
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query.begin().join(qStringValueAsSymbol).end(),
});
// "foo${bar}baz"
const qTemplateString = good_enough_parser_1.query
    .tree({
    type: 'string-tree',
    maxDepth: 2,
    preHandler: (ctx) => {
        ctx.tmpTokenStore.templateTokens = [];
        return ctx;
    },
    search: good_enough_parser_1.query.alt(qStringValue.handler((ctx) => {
        ctx.tmpTokenStore.templateTokens?.push(...ctx.varTokens);
        ctx.varTokens = [];
        return ctx;
    }), qPropertyAccessIdentifier.handler((ctx) => {
        ctx.tmpTokenStore.templateTokens?.push(...ctx.varTokens);
        ctx.varTokens = [];
        return ctx;
    }), qVariableAccessIdentifier.handler((ctx) => {
        ctx.tmpTokenStore.templateTokens?.push(...ctx.varTokens);
        ctx.varTokens = [];
        return ctx;
    })),
})
    .handler((ctx) => {
    ctx.varTokens = ctx.tmpTokenStore.templateTokens;
    return ctx;
});
// foo = "1.2.3"
const qGroovySingleVarAssignment = qVariableAssignmentIdentifier
    .op('=')
    .handler(common_1.coalesceVariable)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'keyToken'))
    .join(qStringValue)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'valToken'))
    .handler(handlers_1.handleAssignment)
    .handler(common_1.cleanupTempVars);
// set("foo", "1.2.3")
const qKotlinSingleVarAssignment = good_enough_parser_1.query
    .sym((0, regex_1.regEx)(/^(?:set|version)$/))
    .tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .join(qStringValue)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'keyToken'))
        .op(',')
        .join(qStringValue)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'valToken'))
        .handler(handlers_1.handleAssignment)
        .end(),
})
    .handler(common_1.cleanupTempVars);
// "foo:bar:1.2.3"
const qDependenciesSimpleString = qStringValue
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'stringToken'))
    .handler(handlers_1.handleDepSimpleString)
    .handler(common_1.cleanupTempVars);
// "foo:bar:$baz"
const qDependenciesInterpolation = qTemplateString
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'templateStringTokens'))
    .handler(handlers_1.handleDepInterpolation)
    .handler(common_1.cleanupTempVars);
// group: "foo", name: "bar", version: "1.2.3"
const qGroovyMapNotationDependencies = good_enough_parser_1.query
    .sym('group')
    .op(':')
    .alt(qTemplateString, qVariableAccessIdentifier)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'groupId'))
    .op(',')
    .sym('name')
    .op(':')
    .alt(qTemplateString, qVariableAccessIdentifier)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'artifactId'))
    .op(',')
    .sym('version')
    .op(':')
    .alt(qTemplateString, qVariableAccessIdentifier)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'version'))
    .handler(handlers_1.handleLongFormDep)
    .handler(common_1.cleanupTempVars);
// (group = "foo", name = "bar", version = "1.2.3")
const qKotlinMapNotationDependencies = good_enough_parser_1.query
    .tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .sym('group')
        .op('=')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'groupId'))
        .op(',')
        .sym('name')
        .op('=')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'artifactId'))
        .op(',')
        .sym('version')
        .op('=')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'version')),
})
    .handler(handlers_1.handleLongFormDep)
    .handler(common_1.cleanupTempVars);
// id "foo.bar" version "1.2.3"
// kotlin("jvm") version "1.3.71"
const qPlugins = good_enough_parser_1.query
    .sym((0, regex_1.regEx)(/^(?:id|kotlin)$/), common_1.storeVarToken)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'methodName'))
    .alt(qStringValue, good_enough_parser_1.query.tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query.begin().join(qStringValue).end(),
}))
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'pluginName'))
    .sym('version')
    .alt(qTemplateString, qPropertyAccessIdentifier, qVariableAccessIdentifier)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'version'))
    .handler(handlers_1.handlePlugin)
    .handler(common_1.cleanupTempVars);
// mavenCentral()
// mavenCentral { ... }
const qPredefinedRegistries = good_enough_parser_1.query
    .sym((0, regex_1.regEx)(`^(?:${Object.keys(common_1.REGISTRY_URLS).join('|')})$`), common_1.storeVarToken)
    .alt(good_enough_parser_1.query.tree({
    type: 'wrapped-tree',
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query.begin().end(),
}), good_enough_parser_1.query.tree({
    type: 'wrapped-tree',
    startsWith: '{',
    endsWith: '}',
}))
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'registryUrl'))
    .handler(handlers_1.handlePredefinedRegistryUrl)
    .handler(common_1.cleanupTempVars);
// maven(url = uri("https://foo.bar/baz"))
// maven { name = some; url = "https://foo.bar/${name}" }
const qCustomRegistryUrl = good_enough_parser_1.query
    .sym('maven')
    .alt(good_enough_parser_1.query.tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .opt(good_enough_parser_1.query.sym('url').op('='))
        .alt(good_enough_parser_1.query.sym('uri').tree({
        maxDepth: 1,
        search: good_enough_parser_1.query.alt(qTemplateString, qVariableAccessIdentifier),
    }), good_enough_parser_1.query.alt(qTemplateString, qVariableAccessIdentifier))
        .end(),
}), good_enough_parser_1.query.tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '{',
    endsWith: '}',
    search: good_enough_parser_1.query.alt(good_enough_parser_1.query
        .sym('name')
        .opt(good_enough_parser_1.query.op('='))
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'name')), good_enough_parser_1.query
        .sym('url')
        .opt(good_enough_parser_1.query.op('='))
        .alt(good_enough_parser_1.query.sym('uri').tree({
        maxDepth: 1,
        search: good_enough_parser_1.query.alt(qTemplateString, qVariableAccessIdentifier),
    }), good_enough_parser_1.query.alt(qTemplateString, qVariableAccessIdentifier)), good_enough_parser_1.query.sym('setUrl').tree({
        maxDepth: 1,
        startsWith: '(',
        endsWith: ')',
        search: good_enough_parser_1.query
            .begin()
            .alt(qTemplateString, qVariableAccessIdentifier)
            .end(),
    })),
}))
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'registryUrl'))
    .handler(handlers_1.handleCustomRegistryUrl)
    .handler(common_1.cleanupTempVars);
const qRegistryUrls = good_enough_parser_1.query.alt(good_enough_parser_1.query.sym('publishing').tree(), qPredefinedRegistries, qCustomRegistryUrl);
const qVersionCatalogVersion = good_enough_parser_1.query
    .op('.')
    .alt(
// library("kotlin-reflect", "org.jetbrains.kotlin", "kotlin-reflect").versionRef("kotlin")
good_enough_parser_1.query.sym('versionRef').tree({
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query.begin().join(qStringValueAsSymbol).end(),
}), 
// library("android-gradle", "com.android.tools.build", "gradle").version("${agp}")
good_enough_parser_1.query.sym('version').tree({
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .alt(qTemplateString, qVariableAccessIdentifier)
        .end(),
}))
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'version'));
// library("foo.bar", "foo", "bar")
const qVersionCatalogDependencies = good_enough_parser_1.query
    .sym('library', common_1.storeVarToken)
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'methodName'))
    .tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .join(qStringValue)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'alias'))
        .op(',')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'groupId'))
        .op(',')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'artifactId'))
        .end(),
})
    .opt(qVersionCatalogVersion)
    .handler(handlers_1.handleLibraryDep)
    .handler(common_1.cleanupTempVars);
// someMethod("foo", "bar", "1.2.3")
const qLongFormDep = good_enough_parser_1.query
    .opt(good_enough_parser_1.query.sym(common_1.storeVarToken).handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'methodName')))
    .tree({
    type: 'wrapped-tree',
    maxDepth: 1,
    maxMatches: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'groupId'))
        .op(',')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'artifactId'))
        .op(',')
        .alt(qTemplateString, qVariableAccessIdentifier)
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'version'))
        .end(),
})
    .handler(handlers_1.handleLongFormDep)
    .handler(common_1.cleanupTempVars);
const qApplyFromFile = good_enough_parser_1.query
    .alt(qTemplateString, // apply from: 'foo.gradle'
qPropertyAccessIdentifier, // apply(from = property("foo"))
good_enough_parser_1.query
    .alt(good_enough_parser_1.query
    .opt(good_enough_parser_1.query.sym((0, regex_1.regEx)(/^(?:rootProject|project)$/)).op('.'))
    .sym('file'), good_enough_parser_1.query.opt(good_enough_parser_1.query.sym('new')).sym('File'))
    .tree({
    maxDepth: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query
        .begin()
        .opt(good_enough_parser_1.query
        .alt(qTemplateString, qPropertyAccessIdentifier, qVariableAccessIdentifier)
        .op(',')
        .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'parentPath')))
        .alt(qTemplateString, qPropertyAccessIdentifier, qVariableAccessIdentifier)
        .end(),
}))
    .handler((ctx) => (0, common_1.storeInTokenMap)(ctx, 'scriptFile'));
const qApplyFrom = good_enough_parser_1.query
    .sym('apply')
    .alt(good_enough_parser_1.query // apply from: rootProject.file("basedir", "foo/bar.gradle")
    .sym('from')
    .op(':')
    .join(qApplyFromFile), good_enough_parser_1.query // apply(from = File(base, "bar.gradle"))
    .tree({
    maxDepth: 1,
    maxMatches: 1,
    startsWith: '(',
    endsWith: ')',
    search: good_enough_parser_1.query.begin().sym('from').op('=').join(qApplyFromFile).end(),
}))
    .handler(handlers_1.handleApplyFrom)
    .handler(common_1.cleanupTempVars);
function parseGradle(input, initVars = {}, packageFile = '', fileContents = {}, recursionDepth = 0) {
    let vars = { ...initVars };
    const deps = [];
    const urls = [];
    const query = good_enough_parser_1.query.tree({
        type: 'root-tree',
        maxDepth: 32,
        search: good_enough_parser_1.query.alt(qGroovySingleVarAssignment, qKotlinSingleVarAssignment, qDependenciesSimpleString, qDependenciesInterpolation, qGroovyMapNotationDependencies, qKotlinMapNotationDependencies, qPlugins, qRegistryUrls, qVersionCatalogDependencies, qLongFormDep, qApplyFrom),
    });
    const parsedResult = groovy.query(input, query, {
        packageFile,
        fileContents,
        recursionDepth,
        globalVars: initVars,
        deps: [],
        depRegistryUrls: [],
        varTokens: [],
        tmpTokenStore: {},
        tokenMap: {},
    });
    if (parsedResult) {
        deps.push(...parsedResult.deps);
        vars = { ...vars, ...parsedResult.globalVars };
        urls.push(...parsedResult.depRegistryUrls);
    }
    return { deps, urls, vars };
}
exports.parseGradle = parseGradle;
const propWord = '[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*';
const propRegex = (0, regex_1.regEx)(`^(?<leftPart>\\s*(?<key>${propWord})\\s*[= :]\\s*['"]?)(?<value>[^\\s'"]+)['"]?\\s*$`);
function parseProps(input, packageFile) {
    let offset = 0;
    const vars = {};
    const deps = [];
    for (const line of input.split(regex_1.newlineRegex)) {
        const lineMatch = propRegex.exec(line);
        if (lineMatch?.groups) {
            const { key, value, leftPart } = lineMatch.groups;
            if ((0, utils_1.isDependencyString)(value)) {
                const dep = (0, utils_1.parseDependencyString)(value);
                if (dep) {
                    deps.push({
                        ...dep,
                        managerData: {
                            fileReplacePosition: offset + leftPart.length + dep.depName.length + 1,
                            packageFile,
                        },
                    });
                }
            }
            else {
                vars[key] = {
                    key,
                    value,
                    fileReplacePosition: offset + leftPart.length,
                    packageFile,
                };
            }
        }
        offset += line.length + 1;
    }
    return { vars, deps };
}
exports.parseProps = parseProps;
//# sourceMappingURL=parser.js.map