diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 00000000..3745b261 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,119 @@ +name: "Copilot Setup Steps" + +# Automatically run the setup steps when they are changed +# Allows for streamlined validation, +# and allow manual testing through the repository's "Actions" tab + +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +env: + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + +jobs: + # The job MUST be called `copilot-setup-steps` + # otherwise it will not be picked up by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + + # Permissions set just for the setup steps + # Copilot has permissions to its branch + + permissions: + # To allow us to clone the repo for setup + contents: read + + # The setup steps - install our dependencies + steps: + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + gradle-version: current + + - name: Checkout Metafor + uses: actions/checkout@v6 + with: + path: metafor + + - name: Determine repository refs + id: repo-refs + shell: bash + env: + BRANCH_NAME: ${{ env.BRANCH_NAME }} + BASE_BRANCH: ${{ github.base_ref }} + run: | + set -euo pipefail + + # For each dependency repository, determine which branch to checkout. + # Priority order: + # 1. A branch with the same name as the current branch + # 2. If this is a PR, the target branch (base_ref) + # 3. The default branch of the repository + + determine_ref() { + local prefix=$1 + local repo=$2 + local url="https://github.com/${repo}.git" + + # Get the default branch + local default_branch + default_branch=$(git ls-remote --symref "$url" HEAD | awk '/^ref:/ {print $2}' | sed 's@refs/heads/@@') + echo "${prefix}_default=${default_branch}" >> "$GITHUB_OUTPUT" + echo "Default branch for ${repo} is '${default_branch}'" + + local ref_to_use="" + + # Priority 1: Same branch name + if [ -n "$(git ls-remote --heads "$url" "refs/heads/${BRANCH_NAME}")" ]; then + ref_to_use="${BRANCH_NAME}" + echo "Using matching branch '${BRANCH_NAME}' in ${repo}" + # Priority 2: PR target branch (if this is a PR) + elif [ -n "${BASE_BRANCH}" ] && [ -n "$(git ls-remote --heads "$url" "refs/heads/${BASE_BRANCH}")" ]; then + ref_to_use="${BASE_BRANCH}" + echo "Using PR target branch '${BASE_BRANCH}' in ${repo}" + # Priority 3: Default branch + else + ref_to_use="${default_branch}" + echo "Using default branch '${default_branch}' for ${repo}" + fi + + echo "${prefix}_ref=${ref_to_use}" >> "$GITHUB_OUTPUT" + } + + determine_ref "lara" "specs-feup/lara-framework" + determine_ref "specs" "specs-feup/specs-java-libs" + + - name: Echo checks + run: | + echo "Weaver branch: ${{ env.BRANCH_NAME }}" + echo "PR target branch (if any): ${{ github.base_ref }}" + echo "Lara framework ref: ${{ steps.repo-refs.outputs.lara_ref }}" + echo "Lara framework default: ${{ steps.repo-refs.outputs.lara_default }}" + echo "Specs-java-libs ref: ${{ steps.repo-refs.outputs.specs_ref }}" + echo "Specs-java-libs default: ${{ steps.repo-refs.outputs.specs_default }}" + + - name: Checkout lara-framework + uses: actions/checkout@v6 + with: + repository: specs-feup/lara-framework + path: lara-framework + ref: ${{ steps.repo-refs.outputs.lara_ref }} + + - name: Checkout specs-java-libs + uses: actions/checkout@v6 + with: + repository: specs-feup/specs-java-libs + path: specs-java-libs + ref: ${{ steps.repo-refs.outputs.specs_ref }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8f687a7b..02d58f58 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -19,11 +19,6 @@ permissions: env: JAVA_VERSION: 21 BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - # Setting default branch to staging assuming PRs will be done against the staging versions of the repository - # main versions will just receive what comes from the staging - DEFAULT_BRANCH: ${{ github.base_ref || 'staging' }} - #SPECS_JAVA_LIBS_BRANCH: ${{ 'master' }} - #LARA_FRAMEWORK_BRANCH: ${{ github.head_ref || github.ref_name }} jobs: build-java: @@ -31,8 +26,8 @@ jobs: runs-on: ubuntu-latest outputs: - branch-exists-lara-framework: ${{ steps.Branch-lara-framework.outputs.value }} - branch-exists-specs-java-libs: ${{ steps.Branch-specs-java-libs.outputs.value }} + lara_ref: ${{ steps.repo-refs.outputs.lara_ref }} + specs_ref: ${{ steps.repo-refs.outputs.specs_ref }} steps: - name: Setup Java @@ -48,42 +43,83 @@ jobs: dependency-graph: generate-and-submit - name: Checkout Metafor - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: path: metafor - - name: Check if branch exists on lara-framework - id: Branch-lara-framework - run: echo "value=$(git ls-remote --heads https://github.com/specs-feup/lara-framework.git refs/heads/${{ env.BRANCH_NAME }} | wc -l)" >> $GITHUB_OUTPUT - - - name: Check if branch exists on specs-java-libs - id: Branch-specs-java-libs - run: echo "value=$(git ls-remote --heads https://github.com/specs-feup/specs-java-libs.git refs/heads/${{ env.BRANCH_NAME }} | wc -l)" >> $GITHUB_OUTPUT + - name: Determine repository refs + id: repo-refs + shell: bash + env: + BRANCH_NAME: ${{ env.BRANCH_NAME }} + BASE_BRANCH: ${{ github.base_ref }} + run: | + set -euo pipefail + + # For each dependency repository, determine which branch to checkout. + # Priority order: + # 1. A branch with the same name as the current branch + # 2. If this is a PR, the target branch (base_ref) + # 3. The default branch of the repository + + determine_ref() { + local prefix=$1 + local repo=$2 + local url="https://github.com/${repo}.git" + + # Get the default branch + local default_branch + default_branch=$(git ls-remote --symref "$url" HEAD | awk '/^ref:/ {print $2}' | sed 's@refs/heads/@@') + echo "${prefix}_default=${default_branch}" >> "$GITHUB_OUTPUT" + echo "Default branch for ${repo} is '${default_branch}'" + + local ref_to_use="" + + # Priority 1: Same branch name + if [ -n "$(git ls-remote --heads "$url" "refs/heads/${BRANCH_NAME}")" ]; then + ref_to_use="${BRANCH_NAME}" + echo "Using matching branch '${BRANCH_NAME}' in ${repo}" + # Priority 2: PR target branch (if this is a PR) + elif [ -n "${BASE_BRANCH}" ] && [ -n "$(git ls-remote --heads "$url" "refs/heads/${BASE_BRANCH}")" ]; then + ref_to_use="${BASE_BRANCH}" + echo "Using PR target branch '${BASE_BRANCH}' in ${repo}" + # Priority 3: Default branch + else + ref_to_use="${default_branch}" + echo "Using default branch '${default_branch}' for ${repo}" + fi + + echo "${prefix}_ref=${ref_to_use}" >> "$GITHUB_OUTPUT" + } + + determine_ref "lara" "specs-feup/lara-framework" + determine_ref "specs" "specs-feup/specs-java-libs" - name: Echo checks run: | - echo "Branch-lara-framework: ${{ steps.Branch-lara-framework.outputs.value }}" - echo "Branch-specs-java-libs: ${{ steps.Branch-specs-java-libs.outputs.value }}" - echo "Branch name: ${{ env.BRANCH_NAME }}" - echo "Default branch: ${{ env.DEFAULT_BRANCH }}" - echo "Branch base_ref: ${{ github.base_ref }}" + echo "Weaver branch: ${{ env.BRANCH_NAME }}" + echo "PR target branch (if any): ${{ github.base_ref }}" + echo "Lara framework ref: ${{ steps.repo-refs.outputs.lara_ref }}" + echo "Lara framework default: ${{ steps.repo-refs.outputs.lara_default }}" + echo "Specs-java-libs ref: ${{ steps.repo-refs.outputs.specs_ref }}" + echo "Specs-java-libs default: ${{ steps.repo-refs.outputs.specs_default }}" - name: Checkout lara-framework - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: specs-feup/lara-framework path: lara-framework - ref: ${{ steps.Branch-lara-framework.outputs.value == '1' && env.BRANCH_NAME || 'master' }} + ref: ${{ steps.repo-refs.outputs.lara_ref }} - name: Checkout specs-java-libs - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: specs-feup/specs-java-libs path: specs-java-libs - ref: ${{ steps.Branch-specs-java-libs.outputs.value == '1' && env.BRANCH_NAME || 'master' }} + ref: ${{ steps.repo-refs.outputs.specs_ref }} - name: Checkout flang dumper, to install flang-20 - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: specs-feup/flang-dumper path: flang-dumper @@ -154,16 +190,16 @@ jobs: registry-url: 'https://registry.npmjs.org/' - name: Checkout Metafor - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: path: metafor - name: Checkout lara-framework - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: specs-feup/lara-framework path: lara-framework - ref: ${{ needs.build-java.outputs.branch-exists-lara-framework == '1' && env.BRANCH_NAME || env.DEFAULT_BRANCH }} + ref: ${{ needs.build-java.outputs.lara_ref }} - name: Setup js workspace run: | diff --git a/Fortran-JS/eslint.config.js b/Fortran-JS/eslint.config.js index 2ad231fb..2273574c 100644 --- a/Fortran-JS/eslint.config.js +++ b/Fortran-JS/eslint.config.js @@ -1,9 +1,14 @@ +import { fileURLToPath } from "url"; +import { dirname } from "path"; import typescriptEslint from "typescript-eslint"; import tsdoc from "eslint-plugin-tsdoc"; import jest from "eslint-plugin-jest"; import js from "@eslint/js"; import eslintConfigPrettier from "eslint-config-prettier"; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + export default [ js.configs.recommended, eslintConfigPrettier, @@ -18,14 +23,13 @@ export default [ }, languageOptions: { - tsconfigRootDir: __dirname, - parser: typescriptEslint.parser, ecmaVersion: 5, sourceType: "script", parserOptions: { project: ["./*/tsconfig.json", "./tsconfig.*.json"], + tsconfigRootDir: __dirname, }, }, diff --git a/Fortran-JS/package.json b/Fortran-JS/package.json index 3f8c643e..d0efa151 100644 --- a/Fortran-JS/package.json +++ b/Fortran-JS/package.json @@ -1,6 +1,6 @@ { "name": "@specs-feup/metafor", - "version": "0.0.6", + "version": "0.0.7", "description": "A Fortran source-to-source compiler written in Typescript", "type": "module", "files": [ @@ -57,21 +57,21 @@ "@specs-feup/lara": "~3.5.0" }, "devDependencies": { - "@jest/globals": "^29.7.0", + "@jest/globals": "^30.2.0", "@types/debug": "^4.1.12", "@types/java": "^0.9.6", - "@types/jest": "^29.5.14", + "@types/jest": "^30.0.0", "@types/node": "^20.14.10", - "@types/yargs": "^17.0.33", - "typescript-eslint": "^8.26.1", - "cross-env": "^7.0.3", - "eslint": "^9.22.0", - "eslint-config-prettier": "^10.1.1", - "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-tsdoc": "^0.4.0", - "jest": "^29.7.0", + "@types/yargs": "^17.0.35", + "cross-env": "^10.1.0", + "eslint": "^9.39.2", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-jest": "^29.12.1", + "eslint-plugin-tsdoc": "^0.5.0", + "jest": "^30.2.0", "node-notifier": "^10.0.1", - "ts-jest": "^29.2.6", - "typescript": "^5.8.2" + "ts-jest": "^29.4.6", + "typescript": "^5.9.3", + "typescript-eslint": "^8.52.0" } } diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranJoinpoints.java b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranJoinpoints.java index 7069e164..74303430 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranJoinpoints.java +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranJoinpoints.java @@ -23,16 +23,16 @@ import pt.up.fe.specs.fortran.weaver.joinpoints.GenericFortranJoinpoint; import pt.up.fe.specs.util.SpecsCollections; import pt.up.fe.specs.util.SpecsLogs; -import pt.up.fe.specs.util.classmap.FunctionClassMap; +import pt.up.fe.specs.util.classmap.BiFunctionClassMap; import java.util.List; public class FortranJoinpoints { - private static final FunctionClassMap JOINPOINT_FACTORY; + private static final BiFunctionClassMap JOINPOINT_FACTORY; static { - JOINPOINT_FACTORY = new FunctionClassMap<>(); + JOINPOINT_FACTORY = new BiFunctionClassMap<>(); JOINPOINT_FACTORY.put(Application.class, FProgram::new); JOINPOINT_FACTORY.put(FortranFile.class, FFile::new); @@ -40,31 +40,31 @@ public class FortranJoinpoints { } - private static AFortranWeaverJoinPoint defaultFactory(FortranNode node) { + private static AFortranWeaverJoinPoint defaultFactory(FortranNode node, FortranWeaver weaver) { SpecsLogs.warn("Factory not defined for nodes of class '" + node.getClass().getSimpleName() + "'"); - return new GenericFortranJoinpoint(node); + return new GenericFortranJoinpoint(node, weaver); } - public static AFortranWeaverJoinPoint create(FortranNode node) { + public static AFortranWeaverJoinPoint create(FortranNode node, FortranWeaver weaver) { if (node == null) { SpecsLogs.debug("CxxJoinpoints: tried to create join point from null node, returning undefined"); return null; } - return JOINPOINT_FACTORY.apply(node); + return JOINPOINT_FACTORY.apply(node, weaver); } - public static T create(FortranNode node, Class targetClass) { + public static T create(FortranNode node, FortranWeaver weaver, Class targetClass) { if (targetClass == null) { throw new RuntimeException("Check if you meant to call 'create' with a single argument"); } - return targetClass.cast(create(node)); + return targetClass.cast(create(node, weaver)); } - public static T[] create(List nodes, Class targetClass) { + public static T[] create(List nodes, FortranWeaver weaver, Class targetClass) { return nodes.stream() - .map(node -> create(node, targetClass)) + .map(node -> create(node, weaver, targetClass)) .toArray(size -> SpecsCollections.newArray(targetClass, size)); } } diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.java b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.java index ee5d4274..6a935821 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.java +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.java @@ -3,7 +3,6 @@ import org.lara.interpreter.joptions.config.interpreter.LaraiKeys; import org.lara.interpreter.weaver.interf.AGear; import org.lara.interpreter.weaver.interf.JoinPoint; -import org.lara.interpreter.weaver.interf.WeaverEngine; import org.lara.interpreter.weaver.options.WeaverOption; import org.lara.interpreter.weaver.options.WeaverOptionUtils; import org.lara.interpreter.weaver.utils.SourcesGatherer; @@ -83,7 +82,7 @@ public boolean begin(List sources, File outputDir, DataStore args) { */ @Override public JoinPoint getRootJp() { - return FortranJoinpoints.create(currentRoot); + return FortranJoinpoints.create(currentRoot, this); } /** @@ -143,13 +142,6 @@ public List getOptions() { return WeaverOptionUtils.toWeaverOption(FortranAstOptions.STORE_DEFINITION); } - /** - * Returns thread-local instance of weaver engine. - */ - public static FortranWeaver getFortranWeaver() { - return (FortranWeaver) WeaverEngine.getThreadLocalWeaver(); - } - /** * Builds the language specification, based on the input XML files. * diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.json b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.json index 032eb891..de166c38 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.json +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/FortranWeaver.json @@ -7,6 +7,15 @@ "name": "joinpoint", "extends": "" , "children": [ + { + "type": "attribute", + "tooltip": "Returns an array with the children of the node, ignoring null nodes", + "children": [ + { + "type": "joinpoint[]", + "name": "children" + }] + }, { "type": "attribute", "tooltip": "String with the code represented by this node", @@ -56,6 +65,15 @@ "extends": "joinpoint" , "tooltip": "Represents a source file (e.g., .f90)", "children": [ + { + "type": "attribute", + "tooltip": "the name of the folder", + "children": [ + { + "type": "String", + "name": "foldername" + }] + }, { "type": "attribute", "tooltip": "the name of the file", @@ -65,6 +83,15 @@ "name": "name" }] }, + { + "type": "attribute", + "tooltip": "Returns an array with the children of the node, ignoring null nodes", + "children": [ + { + "type": "joinpoint[]", + "name": "children" + }] + }, { "type": "attribute", "tooltip": "String with the code represented by this node", @@ -113,6 +140,15 @@ "extends": "joinpoint" , "tooltip": "Represents the complete program and is the top-most join point in the hierarchy", "children": [ + { + "type": "attribute", + "tooltip": "Returns an array with the children of the node, ignoring null nodes", + "children": [ + { + "type": "joinpoint[]", + "name": "children" + }] + }, { "type": "attribute", "tooltip": "String with the code represented by this node", @@ -177,6 +213,15 @@ "name": "isLast" }] }, + { + "type": "attribute", + "tooltip": "Returns an array with the children of the node, ignoring null nodes", + "children": [ + { + "type": "joinpoint[]", + "name": "children" + }] + }, { "type": "attribute", "tooltip": "String with the code represented by this node", diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/abstracts/AFortranWeaverJoinPoint.java b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/abstracts/AFortranWeaverJoinPoint.java index c9f75ba7..709afa5f 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/abstracts/AFortranWeaverJoinPoint.java +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/abstracts/AFortranWeaverJoinPoint.java @@ -1,6 +1,7 @@ package pt.up.fe.specs.fortran.weaver.abstracts; import pt.up.fe.specs.fortran.weaver.FortranJoinpoints; +import pt.up.fe.specs.fortran.weaver.FortranWeaver; import pt.up.fe.specs.fortran.weaver.abstracts.joinpoints.AJoinPoint; import pt.up.fe.specs.fortran.weaver.abstracts.joinpoints.AProgram; @@ -11,6 +12,20 @@ */ public abstract class AFortranWeaverJoinPoint extends AJoinPoint { + /** + * + */ + public AFortranWeaverJoinPoint(FortranWeaver weaver){ + super(weaver); + } + /** + * Returns the Weaving Engine this join point pertains to. + */ + @Override + public FortranWeaver getWeaverEngine() { + return (FortranWeaver) super.getWeaverEngine(); + } + /** * Compares the two join points based on their node reference of the used compiler/parsing tool.
* This is the default implementation for comparing two join points.
@@ -29,7 +44,7 @@ public String getCodeImpl() { @Override public AJoinPoint getParentImpl() { - return FortranJoinpoints.create(getNode().getParent()); + return FortranJoinpoints.create(getNode().getParent(), getWeaverEngine()); } @Override @@ -39,6 +54,6 @@ public AProgram getRootImpl() { @Override public AJoinPoint[] getChildrenArrayImpl() { - return FortranJoinpoints.create(getNode().getChildren(), AJoinPoint.class); + return FortranJoinpoints.create(getNode().getChildren(), getWeaverEngine(), AJoinPoint.class); } } diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FFile.java b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FFile.java index 7865d9f7..b43b3422 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FFile.java +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FFile.java @@ -2,13 +2,15 @@ import pt.up.fe.specs.fortran.ast.nodes.FortranNode; import pt.up.fe.specs.fortran.ast.nodes.program.FortranFile; +import pt.up.fe.specs.fortran.weaver.FortranWeaver; import pt.up.fe.specs.fortran.weaver.abstracts.joinpoints.AFile; public class FFile extends AFile { private final FortranFile file; - public FFile(FortranFile file) { + public FFile(FortranFile file, FortranWeaver weaver) { + super(weaver); this.file = file; } diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FProgram.java b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FProgram.java index 9369c217..3ac946f8 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FProgram.java +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/FProgram.java @@ -2,13 +2,16 @@ import pt.up.fe.specs.fortran.ast.nodes.FortranNode; import pt.up.fe.specs.fortran.ast.nodes.program.Application; +import pt.up.fe.specs.fortran.weaver.FortranWeaver; +import pt.up.fe.specs.fortran.weaver.abstracts.joinpoints.AJoinPoint; import pt.up.fe.specs.fortran.weaver.abstracts.joinpoints.AProgram; public class FProgram extends AProgram { private final Application app; - public FProgram(Application app) { + public FProgram(Application app, FortranWeaver weaver) { + super(weaver); this.app = app; } diff --git a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/GenericFortranJoinpoint.java b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/GenericFortranJoinpoint.java index 3c0b0fe8..3899ba04 100644 --- a/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/GenericFortranJoinpoint.java +++ b/FortranWeaver/src/pt/up/fe/specs/fortran/weaver/joinpoints/GenericFortranJoinpoint.java @@ -1,13 +1,15 @@ package pt.up.fe.specs.fortran.weaver.joinpoints; import pt.up.fe.specs.fortran.ast.nodes.FortranNode; +import pt.up.fe.specs.fortran.weaver.FortranWeaver; import pt.up.fe.specs.fortran.weaver.abstracts.AFortranWeaverJoinPoint; public class GenericFortranJoinpoint extends AFortranWeaverJoinPoint { private final FortranNode node; - public GenericFortranJoinpoint(FortranNode node) { + public GenericFortranJoinpoint(FortranNode node, FortranWeaver weaver) { + super(weaver); this.node = node; }