Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev 0.6.2 #62

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
"titleBar.inactiveBackground": "#00cc9999",
"titleBar.inactiveForeground": "#15202b99"
},
"peacock.remoteColor": "#00CC99"
"peacock.remoteColor": "#00CC99",
"basexTools.xquery.profile": "basex-10"
}
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# [0.6.2] 2024-03-31
* inherit processor when importing modules
# [0.6.1] 2024-01-13
* Java function call handling
* xq-catalogs 0.1.2 (%perm)
# [0.6.0] 2023-12-05
* add namespace to DocLink
* suppress XQLT0001 when no content
# [0.5.1] 2023-11-26
* fix typedefs
# [0.5.0] 2023-11-26
Expand Down
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ module.exports = function (grunt) {
// String or array of strings
// determining which files to include.
// This option is grunt's "full" file format.
src: ['test/type_test.js']
src: ['test/module_resolver_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 Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/quodatum/xqlint/release.yml)
[![Libraries.io dependency status for latest release, scoped npm package](https://img.shields.io/librariesio/release/npm/@quodatum/xqlint)](https://www.npmjs.com/package/@quodatum/xqlint)

[npm @quodatum/xqlint](https://www.npmjs.com/package/@quodatum/xqlint)

XQLint parses XQuery files and returns errors and warnings based on static code analysis. It provides the following features:
* Lint: errors and warnings based on static code analysis.
Expand Down
Binary file removed docs/lint.png
Binary file not shown.
29 changes: 22 additions & 7 deletions docs/markers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,30 @@
## standard
see https://docs.basex.org/wiki/XQuery_Errors
messages..
```javascript
StaticWarning('W01', 'Avoid this type of import. Use import module namespace instead', pos);
StaticWarning('W02', '"' + uri + '" already bound to the "' + namespace.prefixes.join(', ') + '" prefix', pos);
### 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);`

### W03
```
addWarning('W03', 'Unused variable "' + rootStcx.variables[key].qname.name + '"', rootStcx.variables[key].pos);
```
### W04
```
addWarning('W04', 'Unused module "' + uri + '"', namespace.pos);
```
### W05
addWarning('W05', 'Untyped return value', name.pos);

### XQST0009
addWarning('XQST0009', 'No XML Schema support "' + uri + '"', namespace.pos);

### XQST0059
StaticError('XQST0059', 'module "' + uri + '" not found', pos);
### XQST0088
StaticError('XQST0088', 'empty target namespace in module import or module declaration', pos);
### XQST0047
StaticError('XQST0047', '"' + uri + '": duplicate target namespace', pos);

StaticError('XQST0033', '"' + prefix + '": namespace prefix already bound to "' + namespace.uri + '"', pos);
StaticError('XPST0081', '"' + qname.prefix + '": can not expand prefix of lexical QName to namespace URI', pos);
StaticError('XQST0048', '"' + qname.prefix + ':' + qname.name + '": Qname not library namespace', pos);
Expand All @@ -31,9 +42,13 @@ StaticError('XPST0008', '"' + qname.name + '": undeclared variable', pos);
StaticError('XPST0008', '"' + qname.name + '#' + arity + '": undeclared function', pos);
StaticError('XQST0048', '"' + qname.prefix + ':' + qname.name + '": Qname not library namespace', pos);
StaticError('XQST0034', '"' + qname.name + '": duplicate function declaration', pos);
```

### formatter/style_check.js
### XPST0003 :Parse error
### XQLT0001 :Unparsed due to previous parser error



## formatter/style_check.js

* [SW01] Detected CRLF
* [SW02] Tabs detected
Expand Down
17 changes: 12 additions & 5 deletions lib/cli/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,19 @@ astCmd

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){
.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 });
var linter = new XQLint(source, { fileName: file, styleCheck: false , processor: xqdocCmd.profile });
var xqdoc = linter.getXQDoc();
console.log(JSON.stringify(xqdoc, null, 2));
});
Expand All @@ -108,8 +115,8 @@ lintCmd.option(
}
)
.option(
'-p, --processor <name>',
'XQuery Processor (e.g. basex-10)',
'-p, --profile <name>',
'XQuery profile (e.g. basex-10)',
function(value) {
return value.toLowerCase();
}
Expand All @@ -128,7 +135,7 @@ lintCmd.option(
};
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.processor });
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) {
Expand Down
10 changes: 7 additions & 3 deletions lib/compiler/static_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,6 @@ exports.StaticContext = function (parent, pos, processor,baseUri) {
return this;
},



getAvailableModuleNamespaces: function () {
return this.root.availableModuleNamespaces;
},
Expand Down Expand Up @@ -307,10 +305,14 @@ exports.StaticContext = function (parent, pos, processor,baseUri) {
pos: pos,
type: type
};

if(type === 'module' && !namespace && ats.length==0) {
//'todo REPO check
throw new StaticError('XQST0059', 'module "' + uri + '" not found', pos);
}
if (namespace && !namespace.override && !(namespace.uri = uri)) {
throw new StaticWarning('W02', '"' + uri + '" already bound to the "' + namespace.prefixes.join(', ') + '" prefix', pos);
}

if (ats && ats.length) {
//console.log(ats[0].url,"*" ,this.baseUri);
this.namespaces[uri].ats = ats.map(setBase,this);
Expand Down Expand Up @@ -461,6 +463,8 @@ exports.StaticContext = function (parent, pos, processor,baseUri) {
if ((qname.uri === 'http://www.w3.org/2005/xpath-functions' ||
(qname.uri === '' && this.root.defaultFunctionNamespaces.concat(this.root.defaultFunctionNamespace).indexOf('http://www.w3.org/2005/xpath-functions') !== -1)) && qname.name === 'concat') {
//do nothing
} else if(qname.uri.startsWith("java:")){

} else if (!fn) {
throw new StaticError('XPST0008', '"' + qname.name + '#' + arity + '": undeclared function', pos);
}
Expand Down
5 changes: 3 additions & 2 deletions lib/compiler/translator.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ exports.Translator = function (rootStcx, ast) {
var markers = [];

var addStaticError = function (e) {
markers.push({
const marker={
pos: e.getPos(),
code: e.getCode(),
level: 'error',
message: '[' + e.getCode() + '] ' + e.getMessage()
});
};
markers.push(marker);
};

var addWarning = function (code, message, pos) {
Expand Down
2 changes: 1 addition & 1 deletion lib/xqdoc/parse_comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ exports.parseComment = function (comment) {

switch (tag) {
case "description":
ann.description += ' ' + line;
ann.description += line+' ' ;
break;
case "param":
if (hasTag) {
Expand Down
1 change: 1 addition & 0 deletions lib/xqdoc/xqdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ exports.XQDoc = function (ast,sctx) {
this.getXQDoc = function (withPos) {
var doc = {
ns: sctx.moduleNamespace,
description:"todo",
prefixes: [prefix],
namespaces: [],
variables: [],
Expand Down
71 changes: 43 additions & 28 deletions lib/xqlint.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ declare module '@quodatum/xqlint' {
public getErrors(): Marker[];
public getWarnings(): Marker[];

public getNamespaces() :Namespaces;
public getNamespaces(): Namespaces;
public getDocLinks(): DocLink[];

public getProcessor(): string;
Expand All @@ -28,19 +28,19 @@ declare module '@quodatum/xqlint' {
export function createStaticContext(processor: string, fileName?: string): any;
export function CodeFormatter(ast: object): any;
export function CodeFormatter(ast: object, newLinesEnabled: boolean, DEBUG: any): any;

export class XQLintOptions {
processor: string;
fileName?: string; // full path
styleCheck?: boolean;
}
export class XQLintCompletion {
name :string;
value :string;
meta :string; //eg type
priority? :number;
identifierRegex? :string; // nameCharRegExp,
snippet? :string // snippets[name]
name: string;
value: string;
meta: string; //eg type
priority?: number;
identifierRegex?: string; // nameCharRegExp,
snippet?: string // snippets[name]
}
//
export class Marker {
Expand All @@ -51,7 +51,7 @@ declare module '@quodatum/xqlint' {
}

//

export class LintRange {
sl: number;
sc: number;
Expand All @@ -60,12 +60,15 @@ declare module '@quodatum/xqlint' {
}

export class XQDoc {
moduleNamespace: string;
ns: string;
prefixes: string[];
description: string;
variables: VarDecl[];
functions: FunDecl[];
queryBody?: LintRange;
}

// abstract syntax tree
export interface Ast {
name: string;
children: Ast[];
Expand All @@ -74,9 +77,20 @@ declare module '@quodatum/xqlint' {
value?: string;
[propName: string]: any;
}
export interface Sctx {


// static context
export interface Sctx {
resolveQName: (value: string, pos: Position) => QName;
getVariable: (qname: QName) => any;
getFunction: (qname: QName, arity: number) => any;
[propName: string]: any;
}
export interface QName {
uri: string;
prefix: string;
name: string;
}

export interface VarDecl {
name: string;
type: string;
Expand All @@ -99,28 +113,29 @@ declare module '@quodatum/xqlint' {
others: string[];
}
export interface Profile {
id :string;
description :string;
modules :string[];
id: string;
description: string;
modules: string[];
}
export type Namespaces ={
[uri: string]: Namespace;
export type Namespaces = {
[uri: string]: Namespace;
}
export interface Namespace {
type :string; //declare or module
prefixes :string[] //
override? :boolean;
pos : LintRange;
ats? : AtLocation[];
uri? :string; //set by getnamespace from prefix
type: string; //declare or module
prefixes: string[] //
override?: boolean;
pos: LintRange;
ats?: AtLocation[];
uri?: string; //set by getnamespace from prefix
}
export interface AtLocation {
url :string; // path to import, maybe relative eg 'page.xqm'
pos : LintRange; // range of uri string
baseUri? :string; // base URI of source
url: string; // path to import, maybe relative eg 'page.xqm'
pos: LintRange; // range of uri string
baseUri?: string; // base URI of source
}
export interface DocLink {
path :string; // full path to import
pos : LintRange; // range of uri string
ns: string; // namespace
path: string; // full path to import
pos: LintRange; // range of uri string
}
}