Stephane Devin · Dec 15, 2023 go to post

after some testing I found out that multiple token have the same attribute number
As I haven't found documentation about wich token is wich attribute number I put it here.
what i found out for wich attribute number equal to wich JS token :
1 : new line or blank space / tabulation
2 : no occurence in my file
3 : no occurence in my file
4 : ( ) [ ] { } ; , : .
5 : " '
6 : comment //
7 : number
8 : no occurence in my file
9: no occurence in my file 
10 : / single slash (probably to delimit regEx)
11 : ^ + | $ (in regEx)
12 : \s (maybe escaped char in regEx)
13 : g (maybe the mode of a regEx)
14 : variable, function name (call and def)
15 :  =
16 : function and var keywords
and I stopped here.

Stephane Devin · Dec 26, 2023 go to post

I have done it 😁 it need some polish but here is the code to accomplish it using the %SyntaxColor library:

Method ExtractJsFunctionBody(jsCodePath As%String, fnName As%String)
{
  
    #; Reading from a file, writing to a temporary streamset syn = ##class(%SyntaxColor).%New(), in = ##class(%Stream.FileCharacter).%New(), out = ##class(%Stream.TmpCharacter).%New()
    // set js content in content var    set content = in.Read($$$MaxStringLength)
   do InStream.Rewind()
   #; Need the "K" flag to get JSON outputdo in.LinkToFile(jsCodePath), syn.Color(in,out,"JS","K")
   #; Get a %DynamicArray from the streamset lines = ##class(%DynamicArray).%FromJSON(out)
   // get list by line of jsCodeset lineList = $listfromstring(content, $char(10))

   // get pos and line of function def begining set iterLines = lines.%GetIterator()
   while iterLines.%GetNext(.linenumber , .line, .type) {

      set value = line.%Get(1)
      if ((value.%Get("s") = 16) &&  (value.%Get("c") = 8)){  
         set value = line.%Get(3)
         if (value.%Get("s") = 14 ){
            set tempFnName = $extract($list(lineList, linenumber + 1),value.%Get("p") + 1, value.%Get("p") + value.%Get("c"))
            if (tempFnName = fnName ){
               set functionLineBegin = linenumber + 1quit
            }
         }
      }
   }
   
   // get pos of function def endingset functionLineEnd = ..braketCounter(iterLines, lineList)
   
   //extract functiun Bodyset functionBody = $listtostring($list(lineList,functionLineBegin,functionLineEnd),$char(10))
   write !!!, functionBody
}

/// Count braket and return the line of the corresponding ending one take an iterrator at the line of the begining of the search and a list of the lines
Method braketCounter(iterLines As%Iterator.AbstractIterator, lineList As%DynamicArray) As%Integer
{
   set countBraket = 1while iterLines.%GetNext(.linenumber , .line, .type) { // we keep the same iterator to continue from where we whereset iterTokens = line.%GetIterator()
      while iterTokens.%GetNext(.key , .value, .type){
         set token = $extract($list(lineList, linenumber + 1),value.%Get("p") + 1, value.%Get("p") + value.%Get("c") )
         if (value.%Get("s") = 4) {
            if (  token = "{"){
               set countBraket = countBraket + 1}
            elseif ( token = "}"){
               set countBraket = countBraket - 1}
            if (countBraket = 0){
               return linenumber 
            }
         }
         
      }
   }
   return"error"
}
Stephane Devin · Feb 15, 2024 go to post

Thanks!
I figured I should revert to the normal read thanks to you

     use0:(:"S")// set read to silent mode to hide password
     read!,"Please enter your password: ", password
     use0:(:"N")// set read to normal mode for not screwing other input
Stephane Devin · May 17, 2024 go to post

Here is a sample code

$$$ThrowOnError(tUtils.CreateCMSStream(tContent,tCertFileName,tKeyFileName,tPassPhrase,.tStream))//the stream is initialized in CreateCMSStream
     zwritetStream
     settStream.Filename="C:\Users\sdevin\Documents\DEV\iris-pkcs7-util\misc\out\test.cms"
     settsc=tStream.%Save()
     zwtsc
     zwtsc2
     zwritetStream

And here is where I create the stream

MethodConvertStringToStream(pString,OutputpStreamAs%Stream.FileBinary)As%Status
{
     setpStream=##class(%Stream.FileBinary).%New()
     dopStream.Write(pString)
     dopStream.Rewind()
     returnpStream
}

convertStreamToString is the last instruction of CreateCMSStream

Stephane Devin · May 17, 2024 go to post

Thanks, The existing part got me. I will check if the file exist beforehand and create it otherwhise

Thank you!
I tried an SQL update first but I got an error :

<Insert/Update operations not supported on this table.>
For the global solution it work fine for me but only if the new method asn't been compiled before

So first add the method then change the global value and finaly compile.

          // Clone the source method and insert it as the first method in the imported class
          if (debug) { write"adding methodname classmethod to "_className,!}
          set clonedMethod = method.%ConstructClone()
          set tSC = classDefinition.Methods.Insert(clonedMethod)
          if ($$$ISERR(tSC)) { quit }
          set tSC = classDefinition.%Save()
          if ($$$ISERR(tSC)) { quit }

 

          // we set the method in first position
          set ^oddDEF(className,"m",methodName,11)=1

 

          // we recompile the class
          set tSC =  $system.OBJ.Compile(classDefinition.Name, "cbk")


If you need to move an already existing methods I suppose that removing it and compiling before should  work fine but is a naive solution(in my case I don't need it).