1// Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14import * as ts from "typescript"; 15import * as jshelpers from "./jshelpers" 16import { LOGE } from "./log" 17export class DiagnosticError { 18 irnode:ts.Node | undefined; 19 code:number; 20 file: ts.SourceFile | undefined; 21 args: (string | number | undefined)[]; 22 23 constructor(irnode:ts.Node | undefined, code:number, file?:ts.SourceFile | undefined, args?:(string | number | undefined)[]) { 24 this.code = code 25 this.irnode = irnode 26 this.file = file ? file : undefined 27 this.args = args ? args : [] 28 } 29} 30 31export function printDiagnostic(diagnostic: ts.Diagnostic) { 32 33 let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); 34 if (diagnostic.file && diagnostic.start!= undefined) { 35 let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); 36 LOGE(`${diagnostic.file.fileName} (${line + 1},${character + 1})`, `${message}`); 37 } else { 38 LOGE("Error",message); 39 } 40 41} 42 43export function createDiagnosticOnFirstToken(file:ts.SourceFile, node: ts.Node ,message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { 44 let span = jshelpers.getSpanOfTokenAtPosition(file, node.pos); 45 let diagnostic = jshelpers.createFileDiagnostic(file,span.start,span.length,message,...args); 46 return diagnostic; 47} 48 49export function createFileDiagnostic(node: ts.Node, message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]) { 50 let diagnostic; 51 let soureceFile: ts.SourceFile = jshelpers.getSourceFileOfNode(node); 52 let span = jshelpers.getErrorSpanForNode(soureceFile, node); 53 switch (node.kind) { 54 case ts.SyntaxKind.Identifier: 55 diagnostic = jshelpers.createFileDiagnostic(soureceFile, span.start, span.length, message, ts.idText(<ts.Identifier>node)); 56 break; 57 case ts.SyntaxKind.PrivateIdentifier: 58 diagnostic = jshelpers.createFileDiagnostic(soureceFile, span.start, span.length, message, ts.idText(<ts.PrivateIdentifier>node)); 59 break; 60 case ts.SyntaxKind.ReturnStatement: 61 diagnostic = createDiagnosticOnFirstToken(soureceFile, node, message, ...args); 62 break; 63 default: 64 diagnostic = jshelpers.createDiagnosticForNode(node, message, ...args); 65 break; 66 } 67 68 return diagnostic; 69} 70 71export function createDiagnostic(file:ts.SourceFile | undefined, location: ts.Node | undefined, message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { 72 var diagnostic; 73 74 if (!location) { 75 return jshelpers.createCompilerDiagnostic(message, ...args); 76 } 77 78 if (file) { 79 diagnostic = createFileDiagnostic(location, message, ...args); 80 } else { 81 diagnostic = jshelpers.createDiagnosticForNode(location, message, ...args) 82 } 83 84 return diagnostic 85} 86 87// @ts-ignore 88function diag(code:number, category:ts.DiagnosticCategory, key:string, message:string, reportsUnnecessary?:{},elidedInCompatabilityPyramid?:{}):ts.DiagnosticMessage { 89 return { code: code, category: category, key: key, message: message, reportsUnnecessary: reportsUnnecessary }; 90} 91 92% def convertPropertyName(origName) 93% result = "" 94% origName.each_char{|char| 95% if char == "*" 96% result += "_Asterisk" 97% elsif char == "/" 98% result += "_Slash" 99% elsif char == ":" 100% result += "_Colon" 101% elsif /\w/.match(char) 102% result += char 103% else 104% result += "_" 105% end 106% } 107% #get rid of all multi-underscores 108% result = result.gsub(/_+/, "_"); 109% 110% #remove any leading underscore, unless it is followed by a number. 111% result = result.gsub(/^_([^\d])/, "$1"); 112% 113% #get rid of all trailing underscores. 114% result = result.gsub(/_$/, ""); 115% return result 116% end 117 118export enum DiagnosticCode { 119% Diagnostic::datas.each do |data| 120% name = data[0] 121% propName = convertPropertyName(name) 122% code = data[1]["code"] 123 <%= propName %> = <%= code %>, 124%end 125}; 126 127export function getDiagnostic(code:DiagnosticCode): ts.DiagnosticMessage|undefined { 128 switch (code) { 129% 130% def createKey(name,code) 131% key = "" 132% name = name.slice(0,100) 133% key = name + "_" + code.to_s 134% return key 135% end 136% 137% def genReportsUnnecessary(reportsUnnecessary) 138% if reportsUnnecessary.nil? 139% return "" 140% end 141% return ", /*reportsUnnecessary*/ " + reportsUnnecessary.to_s 142% end 143% 144% def genElidedInCompatabilityPyramid(elidedInCompatabilityPyramid,reportsUnnecessary) 145% reportsUnnecessaryVal = "" 146% if reportsUnnecessary.nil? || !reportsUnnecessary 147% reportsUnnecessaryVal = ", /*reportsUnnecessary*/ undefined" 148% end 149% if elidedInCompatabilityPyramid.nil? || !elidedInCompatabilityPyramid 150% return "" 151% end 152% return reportsUnnecessaryVal + ", /*elidedInCompatabilityPyramid*/ " + elidedInCompatabilityPyramid.to_s 153% end 154% 155% def genReportsDeprecated(reportsDeprecated,argElidedInCompatabilityPyramid) 156% argElidedInCompatabilityPyramidVal = "" 157% if argElidedInCompatabilityPyramid.nil? 158% argElidedInCompatabilityPyramidVal = ", /*reportsUnnecessary*/ undefined, /*elidedInCompatabilityPyramid*/ undefined" 159% end 160% if reportsDeprecated.nil? || !reportsDeprecated 161% return "" 162% end 163% return argElidedInCompatabilityPyramidVal + "/*reportsDeprecated*/ " + reportsDeprecated.to_s 164% end 165% 166% Diagnostic::datas.each do |data| 167% name = data[0] 168% propName = convertPropertyName(name) 169% diagnosticDetials = data[1] 170% code = diagnosticDetials["code"] 171% category = diagnosticDetials["category"] 172% reportsUnnecessary = diagnosticDetials["reportsUnnecessary"] 173% elidedInCompatabilityPyramid = diagnosticDetials["elidedInCompatabilityPyramid"] 174% reportsDeprecated = diagnosticDetials["reportsDeprecated"] 175% key = createKey(propName,code) 176% argReportsUnnecessary = genReportsUnnecessary(reportsUnnecessary) 177% argElidedInCompatabilityPyramid = genElidedInCompatabilityPyramid(elidedInCompatabilityPyramid,reportsUnnecessary) 178% argReportsDeprecated = genReportsDeprecated(reportsDeprecated,argElidedInCompatabilityPyramid) 179% message = name.to_json + argReportsUnnecessary + argElidedInCompatabilityPyramid + argReportsDeprecated 180 case <%= code %> : 181 return diag(<%= code %>, ts.DiagnosticCategory.<%= category %>, "<%= key %>", <%= message %>); 182% end 183 default : 184 console.log('The syntax error code is not supported.'); 185 return undefined; 186 } 187};