Skip to content
Merged

Dev #65

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# from https://github.com/vincentml/xml-catalog-resolver

name: CI

on: [push]

jobs:
test:
runs-on: ubuntu-latest
env:
BASEX_VERSION: ${{ matrix.basex }}
strategy:
matrix:
java: ["8", "17"]
basex: ["9.7", "9.7.3"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: temurin
architecture: x64

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Run tests
uses: gradle/gradle-build-action@v3
with:
arguments: test
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# [0.6.3] 2025-02-19
* add profiles cmd
* add getSymbols
* fix repeated treewalk
* dependancy change: matchdep -> load-grunt-tasks
* update axios to 1.7.5 (fetch not working)
# [0.6.2] 2024-03-31
* inherit processor when importing modules
# [0.6.1] 2024-01-13
Expand Down
7 changes: 4 additions & 3 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ const { XQLint } = require('./lib/xqlint');

module.exports = function (grunt) {
'use strict';

require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);

grunt.registerMultiTask('rex', 'Generate Parsers', function () {
Expand Down Expand Up @@ -117,7 +116,9 @@ module.exports = function (grunt) {
// String or array of strings
// determining which files to include.
// This option is grunt's "full" file format.
src: ['test/module_resolver_test.js']
//src: ['test/module_resolver_test.js']
//src: ['test/namespace_test.js']
src: ['test/xqdoc_test.js']
//src: ['test/issue_test.js']
//src: ['test/stylecheck_test.js']
//src: ['test/function_test.js']
Expand Down
1 change: 1 addition & 0 deletions docs/markers.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
see https://docs.basex.org/wiki/XQuery_Errors
messages..
### W01

`StaticWarning('W01', 'Avoid this type of import. Use import module namespace instead', pos);`
### W02
`StaticWarning('W02', '"' + uri + '" already bound to the "' + namespace.prefixes.join(', ') + '" prefix', pos);`
Expand Down
248 changes: 137 additions & 111 deletions lib/cli/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ var fs = require('fs');
var ffs = require('final-fs');
var path = require('path');
var cli = require('commander');
const colors=require('colors');
const colors = require('colors');
colors.disable(); // apb
var XQLint = require('../xqlint').XQLint;

var XQueryLexer = require('../lexers/xquery_lexer').XQueryLexer;
var ANSIOutput = require('./outputs/ansi').ANSIOutput;
var CodeFormatter = require('../formatter/formatter').CodeFormatter;

const xqc = require('@quodatum/xq-catalogs');
var pkg = require('../../package.json');

var getFiles = function(p){
var getFiles = function (p) {
p = path.resolve(path.normalize(p));
var files = [];
if(fs.statSync(p).isFile()){
if (fs.statSync(p).isFile()) {
files.push(p);
} else {
var list = ffs.readdirRecursiveSync(p, true, p);
list.forEach((file) => {
if (['.xq', '.xqm','xqy','.xquery'].indexOf(path.extname(file)) !== -1) {
if (['.xq', '.xqm', 'xqy', '.xquery'].indexOf(path.extname(file)) !== -1) {
files.push(file);
}
});
Expand All @@ -32,16 +32,16 @@ var getFiles = function(p){

var formatCmd = cli.command('format <path>');
formatCmd.description('Format queries')
.action(function(p){
var files = getFiles(p);
files.forEach(function(file){
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint( source, { styleCheck: false });
var formatter = new CodeFormatter(linter.getAST());
var formatted = formatter.format();
console.log(formatted.trim());
.action(function (p) {
var files = getFiles(p);
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint(source, { styleCheck: false });
var formatter = new CodeFormatter(linter.getAST());
var formatted = formatter.format();
console.log(formatted.trim());
});
});
});

var highlightCmd = cli.command('highlight <path>');
/* highlightCmd.option(
Expand All @@ -52,122 +52,148 @@ var highlightCmd = cli.command('highlight <path>');
) */

highlightCmd
.description('Highlight queries. ANSI terminal o/p')
.action(function(p){
var files = getFiles(p);
files.forEach(function(file){
var source = fs.readFileSync(file, 'utf-8');
var lines = source.split('\n');
var lexer = new XQueryLexer();
var result = [], tokens, state;
lines.forEach(function(line){
tokens = lexer.getLineTokens(line, state);
state = tokens.state;
result.push(tokens);
.description('Highlight queries. ANSI terminal o/p')
.action(function (p) {
var files = getFiles(p);
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf-8');
var lines = source.split('\n');
var lexer = new XQueryLexer();
var result = [], tokens, state;
lines.forEach(function (line) {
tokens = lexer.getLineTokens(line, state);
state = tokens.state;
result.push(tokens);
});
ANSIOutput(result);

});
ANSIOutput(result);

});
});

var astCmd = cli.command('ast <path>');
astCmd
.description('Print AST (abstract syntax tree) as XML')
.action(function(p){
var files = getFiles(p);
files.forEach(function(file){
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint(source, { fileName: file, styleCheck: false });
console.log(linter.printAST());
.description('Print AST (abstract syntax tree) as XML')
.action(function (p) {
var files = getFiles(p);
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint(source, { fileName: file, styleCheck: false });
console.log(linter.printAST());
});
});
});

var xqdocCmd = cli.command('xqdoc <path>');
xqdocCmd
.option(
'-p, --profile <name>',
'XQuery profile (e.g. basex-10)',
function(value) {
return value.toLowerCase();
}
)
.description('Print Module XQDoc. A custom json format.')
.action(function(p,xqdocCmd){
var files = getFiles(p);
files.forEach(function(file){
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint(source, { fileName: file, styleCheck: false , processor: xqdocCmd.profile });
var xqdoc = linter.getXQDoc();
console.log(JSON.stringify(xqdoc, null, 2));
.option(
'-p, --profile <name>',
'XQuery profile (e.g. basex-10)',
function (value) {
return value.toLowerCase();
}
)
.description('Print Module XQDoc. A custom json format.')
.action(function (p, xqdocCmd) {
var files = getFiles(p);
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint(source, { fileName: file, styleCheck: false, processor: xqdocCmd.profile });
var xqdoc = linter.getXQDoc();
console.log(JSON.stringify(xqdoc, null, 2));
});
});
});

var xqSymbols = cli.command('symbols <path>');
xqSymbols
.option(
'-p, --profile <name>',
'XQuery profile (e.g. basex-10)',
function (value) {
return value.toLowerCase();
}
)
.description('VScode style sysmbols. xqlint symbols -pbasex-10 "C:/...')
.action(function (p, xqSymbols) {
var files = getFiles(p);
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf-8');
var linter = new XQLint(source, { fileName: file, styleCheck: false, processor: xqSymbols.profile });
var syms = linter.getSymbols();
console.log(syms);
});
});


var lintCmd = cli.command('lint <path>');
lintCmd.option(
'-e, --emacs',
'Format for Gnu/Emacs flymake.'
)
.option(
'-s, --style-check <yes, no>',
'Check for code formatting.',
function(value){
return value === 'yes';
}
)
.option(
'-p, --profile <name>',
'XQuery profile (e.g. basex-10)',
function(value) {
return value.toLowerCase();
}
)
.description('Check queries')
.action(function(p,lintCmd) {
var files = getFiles(p);
var errors = 0;
var warnings = 0;
var spaces = function(count){
var result = '';
for(var i = 1; i <= count; i++){
result += ' ';
.option(
'-s, --style-check <yes, no>',
'Check for code formatting.',
function (value) {
return value === 'yes';
}
)
.option(
'-p, --profile <name>',
'XQuery profile (e.g. basex-10)',
function (value) {
return value.toLowerCase();
}
return result;
};
files.forEach(function(file){
var source = fs.readFileSync(file, 'utf-8').replace(/^\uFEFF/, '');
var linter = new XQLint(source, { fileName: file, styleCheck: lintCmd.styleCheck, processor: lintCmd.profile });
var markers = linter.getMarkers().sort(function(a, b){ return a.sl - b.sl; });
var lines = source.split('\n');
if(markers.length !== 0) {
if (!lintCmd.emacs) {
console.log(('\n' + file).bold);
linter.getErrors().forEach(function(error){
errors++;
console.log('\t' + (error.pos.sl + 1) + ' |' + (lines[error.pos.sl]));
console.log('\t' + spaces((error.pos.sl + 1 + '').length + 1) + spaces(error.pos.sc + 1) + ('^ ' + error.message));
});
linter.getWarnings().forEach(function(error){
warnings++;
console.log('\t' + (error.pos.sl + 1) + ' |' + (lines[error.pos.sl]));
console.log('\t' + spaces((error.pos.sl + 1 + '').length + 1) + spaces(error.pos.sc + 1) + ('^ ' + error.message));
});
} else { // --emacs
markers.forEach(function(marker){
console.log(marker.level.toUpperCase() + ': ' + file + ':' + (marker.pos.sl + 1) + ':' + (marker.pos.sc) + ':' + marker.level + ' ' + marker.message);
});
)
.description('Check queries')
.action(function (p, lintCmd) {
var files = getFiles(p);
var errors = 0;
var warnings = 0;
var spaces = function (count) {
var result = '';
for (var i = 1; i <= count; i++) {
result += ' ';
}
}
return result;
};
files.forEach(function (file) {
var source = fs.readFileSync(file, 'utf-8').replace(/^\uFEFF/, '');
var linter = new XQLint(source, { fileName: file, styleCheck: lintCmd.styleCheck, processor: lintCmd.profile });
var markers = linter.getMarkers().sort(function (a, b) { return a.sl - b.sl; });
var lines = source.split('\n');
if (markers.length !== 0) {
if (!lintCmd.emacs) {
console.log(('\n' + file).bold);
linter.getErrors().forEach(function (error) {
errors++;
console.log('\t' + (error.pos.sl + 1) + ' |' + (lines[error.pos.sl]));
console.log('\t' + spaces((error.pos.sl + 1 + '').length + 1) + spaces(error.pos.sc + 1) + ('^ ' + error.message));
});
linter.getWarnings().forEach(function (error) {
warnings++;
console.log('\t' + (error.pos.sl + 1) + ' |' + (lines[error.pos.sl]));
console.log('\t' + spaces((error.pos.sl + 1 + '').length + 1) + spaces(error.pos.sc + 1) + ('^ ' + error.message));
});
} else { // --emacs
markers.forEach(function (marker) {
console.log(marker.level.toUpperCase() + ': ' + file + ':' + (marker.pos.sl + 1) + ':' + (marker.pos.sc) + ':' + marker.level + ' ' + marker.message);
});
}
}
});
if (!lintCmd.emacs) {
if (errors === 0 && warnings === 0) {
console.log(('Linted ' + files.length + ' files').green);
} else if (errors > 0) {
throw new Error(('Linted ' + files.length + ' files. Found ' + errors + ' errors and ' + warnings + ' warnings.').red);
} else if (warnings > 0) {
throw new Error(('Linted ' + files.length + ' files. Found ' + errors + ' errors and ' + warnings + ' warnings.').yellow);
}
}
});
var profileCmd = cli.command('profiles ')
.description('list profiles')
.action(function (p, profileCmd) {
console.log(xqc.profiles())
});
if (!lintCmd.emacs) {
if(errors === 0 && warnings === 0) {
console.log(('Linted ' + files.length + ' files').green);
} else if(errors > 0) {
throw new Error(('Linted ' + files.length + ' files. Found ' + errors + ' errors and ' + warnings + ' warnings.').red);
} else if(warnings > 0) {
throw new Error(('Linted ' + files.length + ' files. Found ' + errors + ' errors and ' + warnings + ' warnings.').yellow);
}
}
});

cli.version(pkg.version);
module.exports = cli;
2 changes: 1 addition & 1 deletion lib/parsers/XQueryParser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file was generated on Mon Nov 20, 2023 09:59 (UTC) by REx v5.56 which is Copyright (c) 1979-2023 by Gunther Rademacher <grd@gmx.net>
// This file was generated on Sat Aug 24, 2024 11:16 (UTC) by REx v5.57 which is Copyright (c) 1979-2023 by Gunther Rademacher <grd@gmx.net>
// REx command line: XQueryParser.ebnf -ll 2 -backtrack -tree -javascript -a xqlint

// line 2 "XQueryParser.ebnf"
Expand Down
Loading
Loading