diff --git a/.npmignore b/.npmignore index 9c7e943..209a4c1 100644 --- a/.npmignore +++ b/.npmignore @@ -3,4 +3,5 @@ !dist/**/* !package.json !src/**/* -!test/**/* \ No newline at end of file +!test/**/* +!assets/* \ No newline at end of file diff --git a/demo/markupcheck.html b/demo/markupcheck.html new file mode 100644 index 0000000..9f9070c --- /dev/null +++ b/demo/markupcheck.html @@ -0,0 +1,78 @@ + + + + Apex Markup Check + + + + + + + + + + + +

+/**
+ * @author John Smith
+ */
+@IsTest(Seealldata=true)
+public with sharing class L2Char implements Database.batchable {
+  public static final String ERROR = 0x0001;
+
+  @InvocableMethod(label='my invocable')
+  public static void moveTo(
+    Integer x, 
+    Integer y, 
+    Integer z
+  ) {
+    
+    
+    Account a = new Account();
+    a.Custom__c = 'stringvalue';
+    insert a;
+    Boolean ai = (Boolean) false;
+    System.debug('Should not be called');
+    if (1 > 5 && !Test.isRunningTest()) { // wtf!?
+      Database.insert(myAccounts, false);
+    }
+  }
+
+  @TestSetup
+  private static void makeData(Boolean a){
+    Custom__c c = new Custom__c();
+    
+    for(Account a : acctLis ){
+      ConnectApi.insert a;
+    }
+  }
+
+  @isTest
+  private static void testme(){
+    System.assert(true);
+  }
+
+  @testVisible
+  private List<SelectOption> recordTypes { get; private set; }
+
+  for(Account a : [SELECT Id FROM Account WHERE LastModifiedDate = LAST_N_DAYS:3]){
+    Assert.fail();
+  }
+}
+
+trigger CTrig on Custom__c (before insert){
+  System.debug('inserting a record');
+  upsert myRecord__c;
+}
+
+ + diff --git a/demo/soqlsamples.txt b/demo/soqlsamples.txt new file mode 100644 index 0000000..0e0a1f4 --- /dev/null +++ b/demo/soqlsamples.txt @@ -0,0 +1,60 @@ +[SELECT + Account.Name, + (SELECT FIELDS(ALL) FROM Account.Contacts LIMIT 200) +FROM Account] + +[SELECT Id, FIELDS(ALL) FROM User LIMIT 200] +[SELECT + TYPEOF What + WHEN Account THEN Phone + ELSE Name + END +FROM Event +WHERE CreatedById IN + ( + SELECT CreatedById + FROM Case + )] +[SELECT + TYPEOF What + WHEN Account THEN Id, LastModifiedDate + WHEN Opportunity THEN Id + END +FROM Task] +[SELECT + TYPEOF What + WHEN Account THEN Phone, NumberOfEmployees + WHEN Opportunity THEN Amount, CloseDate + ELSE Name, Email + END +FROM Event] +[SELECT Id, (SELECT Id from OpportunityLineItems) +FROM Opportunity +WHERE Id IN + ( + SELECT OpportunityId + FROM OpportunityLineItem + WHERE totalPrice > 10000 + )] +[SELECT Id FROM Account WHERE CreatedDate = NEXT_N_FISCAL_QUARTERS:6] +[SELECT Id FROM Opportunity WHERE CloseDate = N_WEEKS_AGO:3] +[SELECT Id FROM Account WHERE CreatedDate = YESTERDAY] +[SELECT Id, MSP1__c from CustObj__c WHERE MSP1__c includes ('AAA;BBB','CCC')] +[SELECT Id +FROM Case +WHERE Contact.LastName = null] +[SELECT Title FROM Question WHERE LastReplyDate > 2005-10-08T01:02:03Z WITH DATA CATEGORY Geography__c AT (usa__c, uk__c)] +[SELECT LeadSource, COUNT(Name) cnt +FROM Lead +GROUP BY ROLLUP(LeadSource)] +[SELECT LeadSource, COUNT(Name) cnt +FROM Lead +GROUP BY ROLLUP(LeadSource)] +[SELECT Name, MAX(Amount), MIN(Amount) min, SUM(Amount) +FROM Opportunity +GROUP BY Name] +[SELECT LeadSource, Rating, + GROUPING(LeadSource) grpLS, GROUPING(Rating) grpRating, + COUNT(Name) cnt +FROM Lead +GROUP BY ROLLUP(LeadSource, Rating)] \ No newline at end of file diff --git a/dist/apex.es.min.js b/dist/apex.es.min.js index 1b647d1..318a633 100644 --- a/dist/apex.es.min.js +++ b/dist/apex.es.min.js @@ -1,19 +1,19 @@ /*! `apex` grammar compiled for Highlight.js 11.9.0 */ var hljsGrammar=(()=>{"use strict";return e=>{ -const t=e.regex,a="[a-zA-Z][a-zA-Z_0-9]*",c="\\b"+a+"\\b",n="@"+a,s=/(?=\s*\()/,o=/\s+/,r=/\?\./,i=[{ +const t=e.regex,a="[a-zA-Z][a-zA-Z_0-9]*",c="\\b"+a+"\\b",n="@"+a,o=/(?=\s*\()/,s=/\s+/,r=/\?\./,i=[{ match:/(?>\=|>>>\=|\|\=/,/\&|~|\^|\|/,/<<|>>/,/<\=|>\=|\s(<|>)\s/,/\=\=|!\=/,/\=>/,/!(?=\w)/,/(?<=\s)(\?|:)(?=\s)/,r,/(?)/],g=A.concat(...h),y={ +},T=[/--/,/\+\+/,/\&\&|\|\|/,/\*\=|\/\=|\%\=|\+\=|-\=/,/\&\=|\^\=|<<\=|>>\=|>>>\=|\|\=/,/\&|~|\^|\|/,/<<|>>/,/<\=|>\=|\s(<|>)\s/,/\=\=|!\=/,/\=>/,/!(?=\w)/,/(?<=\s)(\?|:)(?=\s)/,r,/(?)/],g=A.concat(...h),y={ $pattern:t.concat(/(?/,/\<(?=\w)/,/\{|\}/,/\(|\)/,/\{|\}/), -scope:"punctuation",relevance:0},T],D=e.inherit(e.APOS_STRING_MODE,{ +scope:"punctuation",relevance:0},R],C=e.inherit(e.APOS_STRING_MODE,{ scope:"string",relevance:0,contains:[{match:/\\'/,scope:"literal",relevance:0}] -}),w=e.COMMENT("//",/[$\n]/,{relevance:0}),I=[e.COMMENT("/\\*","\\*/",{ +}),D=e.COMMENT("//",/[$\n]/,{relevance:0}),I=[e.COMMENT("/\\*","\\*/",{ relevance:0,contains:[{begin:/\w+@/,relevance:0},{ -match:[/@(?:exception|throws)/,o,a],scope:{1:"doctag",3:"title.class"}, +match:[/@(?:exception|throws)/,s,a],scope:{1:"doctag",3:"title.class"}, relevance:0},{begin:"@[A-Za-z_-]+",scope:"doctag",relevance:0},{ match:[/(?<=@param)\s+/,a],scope:{2:"variable"},relevance:0},{begin:"`",end:"`", -scope:"string",contains:[e.BACKSLASH_ESCAPE],relevance:0}]}),w],_={ -match:t.either(...R),scope:"operator",relevance:0},U={match:/(?+/,endScope:"punctuation",contains:[{match:/\<|\,/, scope:"punctuation"},{match:c,scope:"type"}],relevance:8},{ match:[t.optional(c),/\[/,t.optional(/\d+/),/\]/],scope:{1:"variable", 2:"punctuation",3:"number",4:"punctuation"}},{match:[a,/\[\]/],scope:{1:"type", -2:"punctuation"},relevance:0}],f=[{match:t.concat(n,/\b(?!\s*\()/),scope:"meta" +2:"punctuation"},relevance:0}],M=[{match:t.concat(n,/\b(?!\s*\()/),scope:"meta" },{scope:"meta",begin:[t.concat(n,/\b/),/\s*/,/\(/],beginScope:{3:"punctuation" },end:/\)/,endScope:"punctuation",contains:[{match:[c,/\s*=/],scope:{ -1:"keyword",2:"operator"},contains:[_]},D,p],keywords:{literal:S}}],k={ -match:[/\b[a-zA-Z0-9\.]*Exception/,o,a],scope:{1:"title.class",3:"variable"}, +1:"keyword",2:"operator"},contains:[_]},C,p],keywords:{literal:S}}],k={ +match:[/\b[a-zA-Z0-9\.]*Exception/,s,a],scope:{1:"title.class",3:"variable"}, relevance:0},F={match:[/(?])/],scope:{2:"variable"}, -relevance:0},Y={match:[/(?<=\=\s*\()/,a,"(?=\\)\\s*"+a+")"],scope:{2:"type"}, -relevance:0},P={match:[/\bnew\s+/,a,s],scope:{2:"type"},relevance:0};let W={ +relevance:0},P={match:[/(?<=\=\s*\()/,a,"(?=\\)\\s*"+a+")"],scope:{2:"type"}, +relevance:0},Y={match:[/\bnew\s+/,a,o],scope:{2:"type"},relevance:0};let W={ scope:"params_call",begin:/\(/,beginScope:"punctuation",end:/\)/, endScope:"punctuation",relevance:0,keywords:y,contains:[]};const H=[{ -match:[/(?<=\.)/,a,s],scope:{2:"title.function.invoke"},relevance:1, -contains:[...i],starts:W},{match:[/^\s*/,l(...b),a,s],scope:{ +match:[/(?<=\.)/,a,o],scope:{2:"title.function.invoke"},relevance:1, +contains:[...i],starts:W},{match:[/^\s*/,l(...b),a,o],scope:{ 3:"title.function.invoke"},relevance:1,starts:W}] -;W.contains=[D,P,I,_,M,N,p,U,H,{keywords:{KEYWORDS:y}, +;W.contains=[C,Y,I,_,f,O,p,U,H,{keywords:{KEYWORDS:y}, match:t.concat(/(?<=\s|\(|\,)/,l(...S),a,/\b/,/(?!\.)/),scope:"variable", relevance:0},{match:/\(|\,|\./,scope:"punctuation",relevance:0},{match:a, scope:"variable"}];const x={scope:"params",end:/\)/,endScope:"punctuation", -relevance:1,keywords:y,contains:[p,D,I,M,...N,{match:/\,|\(/,scope:"punctuation" +relevance:1,keywords:y,contains:[p,C,I,f,...O,{match:/\,|\(/,scope:"punctuation" },U,{match:[/(?<=\(|\,)\s*/,a,/(?=\s)/],scope:{2:"type"}},{ -match:[o,a,/\s*(?=[,)])/],scope:{2:"variable"}}]},G=[{ -begin:[/\btrigger/,o,a,o,"on",o,a],beginScope:{1:"keyword",3:"title.class", -5:"operator",7:"type"},end:/(?=\{)/,returnEnd:!0,contains:[I,{begin:/\(/, -end:/\)/,contains:[{ +match:[s,a,/\s*(?=[,)])/],scope:{2:"variable"}}]},G={ +match:[/\bswitch\s+on\s+/,a],scope:{1:"keyword",2:"variable"}};return{ +name:"Apex",aliases:["apex","lightning","soql"],case_insensitive:!0, +disableAutodetect:!1,ignoreIllegals:!1,keywords:y, +illegal:["","\x3c!--","!DOCTYPE",/","<%%",":-",/\bmergesort\(/,/\bvar\s+env\b/,/\bdef\b\s\W:/,/"[^"]+"/,/\(\*|\*\)/], +contains:[I,M,C,p,P,f,[{begin:[/\btrigger/,s,a,s,"on",s,a],beginScope:{ +1:"keyword",3:"title.class",5:"operator",7:"type"},end:/(?=\{)/,returnEnd:!0, +contains:[I,{begin:/\(/,end:/\)/,contains:[{ match:/\b(before|after)\s+(insert|update|delete|merge|undelete)\b/, -scope:"keyword",relevance:5},T]}]},{relevance:5, +scope:"keyword",relevance:5},R]}]},{relevance:5, match:/\b(with|without|inherited)\s+sharing\b/,scope:"keyword"},{ begin:[/(?!\.)/,/\bclass\b(?!\?|\.)/],beginScope:{2:"keyword"},end:/(?=\{)/, relevance:1,keywords:{type:m,keyword:b},contains:[{match:[/(?<=\bclass)\s+/,a], scope:{2:"title.class"}},{returnEnd:!0,endsWithParent:!0, -beginKeywords:"implements extends",end:/\{/,contains:[{ -match:t.concat(/\b/,t.either("schedulable","batchable","queueable","comparable","callable"),/\b\s*(?!>)/), -scope:"title.class.inherited",relevance:8},{match:[c,/(?=\.)/],scope:{ -1:"built_in"}},{match:t.concat(c,/(?=\>)/),scope:"type"},{match:c, -scope:"title.class.inherited"},{match:/<|>|,/,scope:"punctuation"},N], +beginKeywords:"implements extends",end:/\{/,contains:[{match:[c,/(?=\.)/], +scope:{1:"built_in"}},{match:t.concat(c,/(?=\>)/),scope:"type"},{match:c, +scope:"title.class.inherited"},{match:/<|>|,/,scope:"punctuation"},O], relevance:0}]},{begin:[/\benum\s+/,a,/\s*\{/],beginScope:{2:"type", -3:"punctuation"},end:/\}/,endScope:"punctuation",relevance:0,contains:[I,T,{ +3:"punctuation"},end:/\}/,endScope:"punctuation",relevance:0,contains:[I,R,{ match:t.concat(c),scope:"variable.constant"}]},{ -match:[/(public|private|protected)\s+/,a,s],scope:{1:"keyword", +match:[/(public|private|protected)\s+/,a,o],scope:{1:"keyword", 2:"title.function"},starts:x,relevance:1},{ -match:[/(?|\w)\s+/,a,s],scope:{2:"title.function"}, -relevance:1,starts:x}],B={match:[/\bswitch\s+on\s+/,a],scope:{1:"keyword", -2:"variable"}},K={ -keyword:[].concat(...y.keyword).concat("ABOVE_OR_BELOW","ACTIVE","ADVANCED","ALL","ANY","ARRAY","AS","ASC","BY","CATEGORY","CONTAINS","CUSTOM","DATA","DESC","DIVISION","END","FIELDS","FIND","FROM","LAST","METADATA","NETWORK","ON","ORDER","RETURNING","ROLLUP","ROWS","SEARCH","SELECT","SNIPPET","SORT","SPELL_CORRECTION","STANDARD","USER_MODE","WHERE","PricebookId","WITH","SECURITY_ENFORCED","USING","SCOPE","Delegated","Everything","Mine","My_Territory","My_Team_Territory","Team","TYPEOF","ELSE","END","THEN","WHEN").concat("ABOVE","AND","AT","BY","CATEGORY","DATA","FIRST","FOR","GROUP","HAVING","IN","LAST","LIKE","LIMIT","LISTVIEW","NOT","NULLS","OFFSET","OR","REFERENCE","TRACKING","TYPEOF","UPDATE","UPDATE","VIEW","VIEWSTAT"), -type:["AVG","convertCurrency","convertTimezone","COUNT_DISTINCT","COUNT","DISTANCE","EXCLUDES","FORMAT","GEOLOCATION","GROUP BY CUBE","GROUP BY ROLLUP","GROUPING","INCLUDES","MAX","MIN","SUM","toLabel"], -"title.function":["DAY_IN_MONTH","HOUR_IN_DAY","DAY_IN_WEEK","DAY_IN_YEAR","DAY_ONLY","CALENDAR_MONTH","CALENDAR_QUARTER","CALENDAR_YEAR","FISCAL_MONTH","FISCAL_QUARTER","FISCAL_YEAR","TODAY","TOMORROW","YESTERDAY","WEEK_IN_MONTH","WEEK_IN_YEAR"], -literal:y.literal,built_in:g};return{name:"Apex", -aliases:["apex","lightning","soql"],case_insensitive:!0,disableAutodetect:!1, -ignoreIllegals:!1,keywords:y, -illegal:["","\x3c!--","!DOCTYPE",/","<%%",":-",/\bmergesort\(/,/\bvar\s+env\b/,/\bdef\b\s\W:/,/"[^"]+"/,/\(\*|\*\)/], -contains:[I,f,D,p,Y,M,G,[{match:/as\s+(user|system)\b/,scope:"keyword"}],k,{ -match:[/\bfor\b\s*/,/\(/,a,o,a,/\s*/,/:/],scope:{3:"type",5:"variable", -7:"operator"}},H,P,L,N,U,{begin:[/\[/,/\s*(?=(SELECT|FIND)\b)/],end:/\]/, +match:[/(?|\w)\s+/,a,o],scope:{2:"title.function"}, +relevance:1,starts:x}],[{match:/as\s+(user|system)\b/,scope:"keyword"}],k,{ +match:[/\bfor\b\s*/,/\(/,a,s,a,/\s*/,/:/],scope:{3:"type",5:"variable", +7:"operator"}},H,Y,N,O,U,{begin:[/\[/,/\s*(?=(SELECT|FIND)\b)/],end:/\]/, beginScope:{1:"punctuation"},endScope:"punctuation",scope:"soql",relevance:10, -endsWithParent:!0,keywords:K,contains:[{begin:/\bSELECT\b/,beginScope:"keyword", -end:/\bFROM\b/,returnEnd:!0,keywords:K,contains:[T,{ -match:[/(?=[\s\,])/,a,/(?=[\s\,])/],scope:{2:"subst"}}]},p,_,D,T,{match:/\(|\)/, -scope:"punctuation",relevance:0},...i,{begin:[/\bFROM\b/,o],beginScope:{ -1:"keyword"},end:/(?=\bWHERE\b|\]|\s|\))/,contains:[{match:a,scope:"type"},...i] -},{ +endsWithParent:!0,keywords:{literal:y.literal,built_in:g},contains:[p,_,C,R,{ +match:/\(|\)/,scope:"punctuation",relevance:0},...i,{begin:[/\bFROM\b/,s], +beginScope:{1:"keyword"},end:/(?=\bWHERE\b|\]|\s|\))/,contains:[{match:a, +scope:"type"},...i]},{ +match:t.concat(/\b/,t.either("CALENDAR_MONTH","CALENDAR_QUARTER","CALENDAR_YEAR","DAY_IN_MONTH","DAY_IN_WEEK","DAY_IN_YEAR","DAY_ONLY","FISCAL_MONTH","FISCAL_QUARTER","FISCAL_YEAR","HOUR_IN_DAY","WEEK_IN_MONTH","WEEK_IN_YEAR","AVG","convertCurrency","convertTimezone","COUNT_DISTINCT","COUNT","DISTANCE","EXCLUDES","FIELDS","FORMAT","GEOLOCATION","GROUPING","ROLLUP","CUBE","INCLUDES","MAX","MIN","SUM","toLabel"),/\b/), +scope:"title.function"},{match:/\b(GROUP|ORDER)\s+BY\b/,scope:"title.function" +},{match:/\b(TODAY|TOMORROW|YESTERDAY)\b/,scope:"keyword"},{ match:/(NEXT|LAST|THIS)_(90_DAY|DAY|FISCAL_QUARTER|FISCAL_YEAR|MONTH|QUARTER|WEEK|YEAR)S?\b/, scope:"keyword",relevance:8},{ match:[/(NEXT|LAST)_N_(DAY|FISCAL_QUARTER|FISCAL_YEAR|MONTH|QUARTER|WEEK|YEAR)S/,/\s*:\s*/,/\d+/], scope:{1:"keyword",2:"operator",3:"number"},relevance:8},{ -match:[/(?<=:)/,/\s*/,c,/(?!\()/],scope:{3:"variable"},relevance:0},{ -match:[/(?<=:|\.)/,a,/(?=\s*\()/],scope:{2:"title.function.invoke"},relevance:0 -},{match:/:/,scope:"operator",relevance:0}],illegal:"::"},B,F,_,C,i,{ -match:t.concat("(?<=this.)",a,"(?!\\()"),scope:"variable"},{ -match:[t.concat(/\b/,l(...O)),a,o,/(?=\{)/],scope:{2:"property"},relevance:0}]}} -})();export default hljsGrammar; \ No newline at end of file +match:t.concat(/\b/,t.either(...y.keyword,"ABOVE_OR_BELOW","ABOVE","ACTIVE","ADVANCED","ALL","ANY","ARRAY","AS","ASC","BELOW","CATEGORY","CONTAINS","CUSTOM","DATA","DESC","DIVISION","ELSE","END","FIND","FROM","METADATA","NETWORK","ON","PricebookId","RETURNING","ROLLUP","ROWS","SEARCH","SECURITY_ENFORCED","SELECT","SNIPPET","SORT","SPELL_CORRECTION","STANDARD","THEN","USER_MODE","USING","WHEN","WHERE","WITH","SCOPE","Delegated","Everything","Mine","My_Territory","My_Team_Territory","Team","AND","AT","FIRST","FOR","HAVING","IN","LAST","LIKE","LIMIT","LISTVIEW","NOT","NULLS","OFFSET","OR","REFERENCE","TRACKING","TYPEOF","UPDATE","VIEW","VIEWSTAT"),/\b/), +scope:"keyword"},{match:[/(?<=:)/,/\s*/,c,/(?!\()/],scope:{3:"variable"}, +relevance:0},O,{match:[/(?<=:|\.)/,a,/(?=\s*\()/],scope:{ +2:"title.function.invoke"},relevance:0},{match:/:/,scope:"operator",relevance:0 +}],illegal:"::"},G,F,_,w,i,{match:t.concat("(?<=this.)",a,"(?!\\()"), +scope:"variable"},{match:[t.concat(/\b/,l(...L)),a,s,/(?=\{)/],scope:{ +2:"property"},relevance:0}]}}})();export default hljsGrammar; \ No newline at end of file diff --git a/dist/apex.min.js b/dist/apex.min.js index fe510f7..cc28218 100644 --- a/dist/apex.min.js +++ b/dist/apex.min.js @@ -1,19 +1,19 @@ /*! `apex` grammar compiled for Highlight.js 11.9.0 */ (()=>{var e=(()=>{"use strict";return e=>{ -const t=e.regex,a="[a-zA-Z][a-zA-Z_0-9]*",c="\\b"+a+"\\b",n="@"+a,s=/(?=\s*\()/,o=/\s+/,r=/\?\./,i=[{ -match:/(?>\=|>>>\=|\|\=/,/\&|~|\^|\|/,/<<|>>/,/<\=|>\=|\s(<|>)\s/,/\=\=|!\=/,/\=>/,/!(?=\w)/,/(?<=\s)(\?|:)(?=\s)/,r,/(?)/],g=A.concat(...h),y={ +},R=[/--/,/\+\+/,/\&\&|\|\|/,/\*\=|\/\=|\%\=|\+\=|-\=/,/\&\=|\^\=|<<\=|>>\=|>>>\=|\|\=/,/\&|~|\^|\|/,/<<|>>/,/<\=|>\=|\s(<|>)\s/,/\=\=|!\=/,/\=>/,/!(?=\w)/,/(?<=\s)(\?|:)(?=\s)/,i,/(?)/],T=A.concat(...h),y={ $pattern:t.concat(/(?/,/\<(?=\w)/,/\{|\}/,/\(|\)/,/\{|\}/), -scope:"punctuation",relevance:0},T],D=e.inherit(e.APOS_STRING_MODE,{ +scope:"punctuation",relevance:0},g],C=e.inherit(e.APOS_STRING_MODE,{ scope:"string",relevance:0,contains:[{match:/\\'/,scope:"literal",relevance:0}] -}),w=e.COMMENT("//",/[$\n]/,{relevance:0}),I=[e.COMMENT("/\\*","\\*/",{ +}),D=e.COMMENT("//",/[$\n]/,{relevance:0}),I=[e.COMMENT("/\\*","\\*/",{ relevance:0,contains:[{begin:/\w+@/,relevance:0},{ -match:[/@(?:exception|throws)/,o,a],scope:{1:"doctag",3:"title.class"}, +match:[/@(?:exception|throws)/,s,a],scope:{1:"doctag",3:"title.class"}, relevance:0},{begin:"@[A-Za-z_-]+",scope:"doctag",relevance:0},{ match:[/(?<=@param)\s+/,a],scope:{2:"variable"},relevance:0},{begin:"`",end:"`", -scope:"string",contains:[e.BACKSLASH_ESCAPE],relevance:0}]}),w],_={ +scope:"string",contains:[e.BACKSLASH_ESCAPE],relevance:0}]}),D],_={ match:t.either(...R),scope:"operator",relevance:0},U={match:/(?+/,endScope:"punctuation",contains:[{match:/\<|\,/, scope:"punctuation"},{match:c,scope:"type"}],relevance:8},{ match:[t.optional(c),/\[/,t.optional(/\d+/),/\]/],scope:{1:"variable", 2:"punctuation",3:"number",4:"punctuation"}},{match:[a,/\[\]/],scope:{1:"type", -2:"punctuation"},relevance:0}],f=[{match:t.concat(n,/\b(?!\s*\()/),scope:"meta" +2:"punctuation"},relevance:0}],M=[{match:t.concat(n,/\b(?!\s*\()/),scope:"meta" },{scope:"meta",begin:[t.concat(n,/\b/),/\s*/,/\(/],beginScope:{3:"punctuation" },end:/\)/,endScope:"punctuation",contains:[{match:[c,/\s*=/],scope:{ -1:"keyword",2:"operator"},contains:[_]},D,p],keywords:{literal:S}}],k={ -match:[/\b[a-zA-Z0-9\.]*Exception/,o,a],scope:{1:"title.class",3:"variable"}, +1:"keyword",2:"operator"},contains:[_]},C,p],keywords:{literal:S}}],k={ +match:[/\b[a-zA-Z0-9\.]*Exception/,s,a],scope:{1:"title.class",3:"variable"}, relevance:0},F={match:[/(?])/],scope:{2:"variable"}, -relevance:0},Y={match:[/(?<=\=\s*\()/,a,"(?=\\)\\s*"+a+")"],scope:{2:"type"}, -relevance:0},P={match:[/\bnew\s+/,a,s],scope:{2:"type"},relevance:0};let W={ +relevance:0},P={match:[/(?<=\=\s*\()/,a,"(?=\\)\\s*"+a+")"],scope:{2:"type"}, +relevance:0},Y={match:[/\bnew\s+/,a,o],scope:{2:"type"},relevance:0};let W={ scope:"params_call",begin:/\(/,beginScope:"punctuation",end:/\)/, endScope:"punctuation",relevance:0,keywords:y,contains:[]};const H=[{ -match:[/(?<=\.)/,a,s],scope:{2:"title.function.invoke"},relevance:1, -contains:[...i],starts:W},{match:[/^\s*/,l(...b),a,s],scope:{ +match:[/(?<=\.)/,a,o],scope:{2:"title.function.invoke"},relevance:1, +contains:[...r],starts:W},{match:[/^\s*/,l(...b),a,o],scope:{ 3:"title.function.invoke"},relevance:1,starts:W}] -;W.contains=[D,P,I,_,M,N,p,U,H,{keywords:{KEYWORDS:y}, +;W.contains=[C,Y,I,_,f,O,p,U,H,{keywords:{KEYWORDS:y}, match:t.concat(/(?<=\s|\(|\,)/,l(...S),a,/\b/,/(?!\.)/),scope:"variable", relevance:0},{match:/\(|\,|\./,scope:"punctuation",relevance:0},{match:a, scope:"variable"}];const x={scope:"params",end:/\)/,endScope:"punctuation", -relevance:1,keywords:y,contains:[p,D,I,M,...N,{match:/\,|\(/,scope:"punctuation" +relevance:1,keywords:y,contains:[p,C,I,f,...O,{match:/\,|\(/,scope:"punctuation" },U,{match:[/(?<=\(|\,)\s*/,a,/(?=\s)/],scope:{2:"type"}},{ -match:[o,a,/\s*(?=[,)])/],scope:{2:"variable"}}]},G=[{ -begin:[/\btrigger/,o,a,o,"on",o,a],beginScope:{1:"keyword",3:"title.class", -5:"operator",7:"type"},end:/(?=\{)/,returnEnd:!0,contains:[I,{begin:/\(/, -end:/\)/,contains:[{ +match:[s,a,/\s*(?=[,)])/],scope:{2:"variable"}}]},B={ +match:[/\bswitch\s+on\s+/,a],scope:{1:"keyword",2:"variable"}};return{ +name:"Apex",aliases:["apex","lightning","soql"],case_insensitive:!0, +disableAutodetect:!1,ignoreIllegals:!1,keywords:y, +illegal:["","\x3c!--","!DOCTYPE",/","<%%",":-",/\bmergesort\(/,/\bvar\s+env\b/,/\bdef\b\s\W:/,/"[^"]+"/,/\(\*|\*\)/], +contains:[I,M,C,p,P,f,[{begin:[/\btrigger/,s,a,s,"on",s,a],beginScope:{ +1:"keyword",3:"title.class",5:"operator",7:"type"},end:/(?=\{)/,returnEnd:!0, +contains:[I,{begin:/\(/,end:/\)/,contains:[{ match:/\b(before|after)\s+(insert|update|delete|merge|undelete)\b/, -scope:"keyword",relevance:5},T]}]},{relevance:5, +scope:"keyword",relevance:5},g]}]},{relevance:5, match:/\b(with|without|inherited)\s+sharing\b/,scope:"keyword"},{ begin:[/(?!\.)/,/\bclass\b(?!\?|\.)/],beginScope:{2:"keyword"},end:/(?=\{)/, relevance:1,keywords:{type:m,keyword:b},contains:[{match:[/(?<=\bclass)\s+/,a], scope:{2:"title.class"}},{returnEnd:!0,endsWithParent:!0, -beginKeywords:"implements extends",end:/\{/,contains:[{ -match:t.concat(/\b/,t.either("schedulable","batchable","queueable","comparable","callable"),/\b\s*(?!>)/), -scope:"title.class.inherited",relevance:8},{match:[c,/(?=\.)/],scope:{ -1:"built_in"}},{match:t.concat(c,/(?=\>)/),scope:"type"},{match:c, -scope:"title.class.inherited"},{match:/<|>|,/,scope:"punctuation"},N], +beginKeywords:"implements extends",end:/\{/,contains:[{match:[c,/(?=\.)/], +scope:{1:"built_in"}},{match:t.concat(c,/(?=\>)/),scope:"type"},{match:c, +scope:"title.class.inherited"},{match:/<|>|,/,scope:"punctuation"},O], relevance:0}]},{begin:[/\benum\s+/,a,/\s*\{/],beginScope:{2:"type", -3:"punctuation"},end:/\}/,endScope:"punctuation",relevance:0,contains:[I,T,{ +3:"punctuation"},end:/\}/,endScope:"punctuation",relevance:0,contains:[I,g,{ match:t.concat(c),scope:"variable.constant"}]},{ -match:[/(public|private|protected)\s+/,a,s],scope:{1:"keyword", +match:[/(public|private|protected)\s+/,a,o],scope:{1:"keyword", 2:"title.function"},starts:x,relevance:1},{ -match:[/(?|\w)\s+/,a,s],scope:{2:"title.function"}, -relevance:1,starts:x}],B={match:[/\bswitch\s+on\s+/,a],scope:{1:"keyword", -2:"variable"}},K={ -keyword:[].concat(...y.keyword).concat("ABOVE_OR_BELOW","ACTIVE","ADVANCED","ALL","ANY","ARRAY","AS","ASC","BY","CATEGORY","CONTAINS","CUSTOM","DATA","DESC","DIVISION","END","FIELDS","FIND","FROM","LAST","METADATA","NETWORK","ON","ORDER","RETURNING","ROLLUP","ROWS","SEARCH","SELECT","SNIPPET","SORT","SPELL_CORRECTION","STANDARD","USER_MODE","WHERE","PricebookId","WITH","SECURITY_ENFORCED","USING","SCOPE","Delegated","Everything","Mine","My_Territory","My_Team_Territory","Team","TYPEOF","ELSE","END","THEN","WHEN").concat("ABOVE","AND","AT","BY","CATEGORY","DATA","FIRST","FOR","GROUP","HAVING","IN","LAST","LIKE","LIMIT","LISTVIEW","NOT","NULLS","OFFSET","OR","REFERENCE","TRACKING","TYPEOF","UPDATE","UPDATE","VIEW","VIEWSTAT"), -type:["AVG","convertCurrency","convertTimezone","COUNT_DISTINCT","COUNT","DISTANCE","EXCLUDES","FORMAT","GEOLOCATION","GROUP BY CUBE","GROUP BY ROLLUP","GROUPING","INCLUDES","MAX","MIN","SUM","toLabel"], -"title.function":["DAY_IN_MONTH","HOUR_IN_DAY","DAY_IN_WEEK","DAY_IN_YEAR","DAY_ONLY","CALENDAR_MONTH","CALENDAR_QUARTER","CALENDAR_YEAR","FISCAL_MONTH","FISCAL_QUARTER","FISCAL_YEAR","TODAY","TOMORROW","YESTERDAY","WEEK_IN_MONTH","WEEK_IN_YEAR"], -literal:y.literal,built_in:g};return{name:"Apex", -aliases:["apex","lightning","soql"],case_insensitive:!0,disableAutodetect:!1, -ignoreIllegals:!1,keywords:y, -illegal:["","\x3c!--","!DOCTYPE",/","<%%",":-",/\bmergesort\(/,/\bvar\s+env\b/,/\bdef\b\s\W:/,/"[^"]+"/,/\(\*|\*\)/], -contains:[I,f,D,p,Y,M,G,[{match:/as\s+(user|system)\b/,scope:"keyword"}],k,{ -match:[/\bfor\b\s*/,/\(/,a,o,a,/\s*/,/:/],scope:{3:"type",5:"variable", -7:"operator"}},H,P,L,N,U,{begin:[/\[/,/\s*(?=(SELECT|FIND)\b)/],end:/\]/, +match:[/(?|\w)\s+/,a,o],scope:{2:"title.function"}, +relevance:1,starts:x}],[{match:/as\s+(user|system)\b/,scope:"keyword"}],k,{ +match:[/\bfor\b\s*/,/\(/,a,s,a,/\s*/,/:/],scope:{3:"type",5:"variable", +7:"operator"}},H,Y,N,O,U,{begin:[/\[/,/\s*(?=(SELECT|FIND)\b)/],end:/\]/, beginScope:{1:"punctuation"},endScope:"punctuation",scope:"soql",relevance:10, -endsWithParent:!0,keywords:K,contains:[{begin:/\bSELECT\b/,beginScope:"keyword", -end:/\bFROM\b/,returnEnd:!0,keywords:K,contains:[T,{ -match:[/(?=[\s\,])/,a,/(?=[\s\,])/],scope:{2:"subst"}}]},p,_,D,T,{match:/\(|\)/, -scope:"punctuation",relevance:0},...i,{begin:[/\bFROM\b/,o],beginScope:{ -1:"keyword"},end:/(?=\bWHERE\b|\]|\s|\))/,contains:[{match:a,scope:"type"},...i] -},{ +endsWithParent:!0,keywords:{literal:y.literal,built_in:T},contains:[p,_,C,g,{ +match:/\(|\)/,scope:"punctuation",relevance:0},...r,{begin:[/\bFROM\b/,s], +beginScope:{1:"keyword"},end:/(?=\bWHERE\b|\]|\s|\))/,contains:[{match:a, +scope:"type"},...r]},{ +match:t.concat(/\b/,t.either("CALENDAR_MONTH","CALENDAR_QUARTER","CALENDAR_YEAR","DAY_IN_MONTH","DAY_IN_WEEK","DAY_IN_YEAR","DAY_ONLY","FISCAL_MONTH","FISCAL_QUARTER","FISCAL_YEAR","HOUR_IN_DAY","WEEK_IN_MONTH","WEEK_IN_YEAR","AVG","convertCurrency","convertTimezone","COUNT_DISTINCT","COUNT","DISTANCE","EXCLUDES","FIELDS","FORMAT","GEOLOCATION","GROUPING","ROLLUP","CUBE","INCLUDES","MAX","MIN","SUM","toLabel"),/\b/), +scope:"title.function"},{match:/\b(GROUP|ORDER)\s+BY\b/,scope:"title.function" +},{match:/\b(TODAY|TOMORROW|YESTERDAY)\b/,scope:"keyword"},{ match:/(NEXT|LAST|THIS)_(90_DAY|DAY|FISCAL_QUARTER|FISCAL_YEAR|MONTH|QUARTER|WEEK|YEAR)S?\b/, scope:"keyword",relevance:8},{ match:[/(NEXT|LAST)_N_(DAY|FISCAL_QUARTER|FISCAL_YEAR|MONTH|QUARTER|WEEK|YEAR)S/,/\s*:\s*/,/\d+/], scope:{1:"keyword",2:"operator",3:"number"},relevance:8},{ -match:[/(?<=:)/,/\s*/,c,/(?!\()/],scope:{3:"variable"},relevance:0},{ -match:[/(?<=:|\.)/,a,/(?=\s*\()/],scope:{2:"title.function.invoke"},relevance:0 -},{match:/:/,scope:"operator",relevance:0}],illegal:"::"},B,F,_,C,i,{ -match:t.concat("(?<=this.)",a,"(?!\\()"),scope:"variable"},{ -match:[t.concat(/\b/,l(...O)),a,o,/(?=\{)/],scope:{2:"property"},relevance:0}]}} -})();hljs.registerLanguage("apex",e)})(); \ No newline at end of file +match:t.concat(/\b/,t.either(...y.keyword,"ABOVE_OR_BELOW","ABOVE","ACTIVE","ADVANCED","ALL","ANY","ARRAY","AS","ASC","BELOW","CATEGORY","CONTAINS","CUSTOM","DATA","DESC","DIVISION","ELSE","END","FIND","FROM","METADATA","NETWORK","ON","PricebookId","RETURNING","ROLLUP","ROWS","SEARCH","SECURITY_ENFORCED","SELECT","SNIPPET","SORT","SPELL_CORRECTION","STANDARD","THEN","USER_MODE","USING","WHEN","WHERE","WITH","SCOPE","Delegated","Everything","Mine","My_Territory","My_Team_Territory","Team","AND","AT","FIRST","FOR","HAVING","IN","LAST","LIKE","LIMIT","LISTVIEW","NOT","NULLS","OFFSET","OR","REFERENCE","TRACKING","TYPEOF","UPDATE","VIEW","VIEWSTAT"),/\b/), +scope:"keyword"},{match:[/(?<=:)/,/\s*/,c,/(?!\()/],scope:{3:"variable"}, +relevance:0},O,{match:[/(?<=:|\.)/,a,/(?=\s*\()/],scope:{ +2:"title.function.invoke"},relevance:0},{match:/:/,scope:"operator",relevance:0 +}],illegal:"::"},B,F,_,w,r,{match:t.concat("(?<=this.)",a,"(?!\\()"), +scope:"variable"},{match:[t.concat(/\b/,l(...L)),a,s,/(?=\{)/],scope:{ +2:"property"},relevance:0}]}}})();hljs.registerLanguage("apex",e)})(); \ No newline at end of file diff --git a/src/languages/apex.js b/src/languages/apex.js index 57f969d..a5d4121 100644 --- a/src/languages/apex.js +++ b/src/languages/apex.js @@ -126,14 +126,6 @@ export default function (hljs) { 'convertLead' ]; - const SYSTEM_INTERFACES = [ - 'schedulable', - 'batchable', - 'queueable', - 'comparable', - 'callable' - ]; - const NAMESPACE_LIST = [ //'ApexPages', // also a System class 'AppLauncher', @@ -668,15 +660,6 @@ export default function (hljs) { beginKeywords: 'implements extends', end: /\{/, contains: [ - { - match: regex.concat( - /\b/, - regex.either(...SYSTEM_INTERFACES), - /\b\s*(?!>)/ - ), - scope: 'title.class.inherited', - relevance: 8 - }, { match: [APEX_IDENT_WORD_RE, /(?=\.)/], scope: { 1: 'built_in' } @@ -814,14 +797,6 @@ export default function (hljs) { match: /as\s+(user|system)\b/, scope: 'keyword' } - /* { - match: [ - regex.concat(/\b/, regex.either(...DMLS)), - /\s+(?!\()/, - regex.optional(/as\s+(user|system)\b/) - ], - scope: { 3: 'keyword' } - } */ ]; /** @@ -831,6 +806,7 @@ export default function (hljs) { const SOQL_KEYWORDS = [ // * orange italic 'ABOVE_OR_BELOW', + 'ABOVE', 'ACTIVE', 'ADVANCED', 'ALL', @@ -838,63 +814,53 @@ export default function (hljs) { 'ARRAY', 'AS', 'ASC', - 'BY', + 'BELOW', 'CATEGORY', 'CONTAINS', 'CUSTOM', 'DATA', 'DESC', 'DIVISION', + 'ELSE', 'END', - 'FIELDS', 'FIND', 'FROM', - 'LAST', 'METADATA', 'NETWORK', 'ON', - 'ORDER', + 'PricebookId', 'RETURNING', 'ROLLUP', 'ROWS', 'SEARCH', + 'SECURITY_ENFORCED', 'SELECT', 'SNIPPET', 'SORT', 'SPELL_CORRECTION', 'STANDARD', + 'THEN', 'USER_MODE', + 'USING', + 'WHEN', 'WHERE', - 'PricebookId', 'WITH', - 'SECURITY_ENFORCED', - 'USING', 'SCOPE', 'Delegated', 'Everything', 'Mine', 'My_Territory', 'My_Team_Territory', - 'Team', - 'TYPEOF', - 'ELSE', - 'END', - 'THEN', - 'WHEN' + 'Team' /* /USING\s+SCOPE\s*(Delegated|Everything|Mine|My_Territory|My_Team_Territory|Team)/, */ ]; const SOQL_OPERATORS = [ // * orange italic - 'ABOVE', 'AND', 'AT', - 'BY', - 'CATEGORY', - 'DATA', 'FIRST', 'FOR', - 'GROUP', 'HAVING', 'IN', 'LAST', @@ -909,7 +875,6 @@ export default function (hljs) { 'TRACKING', 'TYPEOF', 'UPDATE', - 'UPDATE', 'VIEW', 'VIEWSTAT' ]; @@ -923,11 +888,12 @@ export default function (hljs) { 'COUNT', 'DISTANCE', 'EXCLUDES', + 'FIELDS', 'FORMAT', 'GEOLOCATION', - 'GROUP BY CUBE', - 'GROUP BY ROLLUP', 'GROUPING', + 'ROLLUP', + 'CUBE', 'INCLUDES', 'MAX', 'MIN', @@ -935,52 +901,27 @@ export default function (hljs) { 'toLabel' ]; - const SOQL_DATE_FUNCTIONS = [ + const SOQL_DATE_SELECT_FUNCTIONS = [ + 'CALENDAR_MONTH', + 'CALENDAR_QUARTER', + 'CALENDAR_YEAR', 'DAY_IN_MONTH', - 'HOUR_IN_DAY', 'DAY_IN_WEEK', 'DAY_IN_YEAR', 'DAY_ONLY', - 'CALENDAR_MONTH', - 'CALENDAR_QUARTER', - 'CALENDAR_YEAR', 'FISCAL_MONTH', 'FISCAL_QUARTER', 'FISCAL_YEAR', - 'TODAY', - 'TOMORROW', - 'YESTERDAY', + 'HOUR_IN_DAY', 'WEEK_IN_MONTH', 'WEEK_IN_YEAR' ]; - const SOQL_SPECIAL_WORDS = { - keyword: [] - .concat(...KEYWORDS.keyword) - .concat(...SOQL_KEYWORDS) - .concat(...SOQL_OPERATORS), // * orange italic - type: SOQL_FUNCTIONS, // * blue italic - 'title.function': SOQL_DATE_FUNCTIONS, // * blue normal - literal: KEYWORDS.literal, - built_in: BUILT_INS - }; - - const SOQL_SELECT = { - begin: /\bSELECT\b/, - beginScope: 'keyword', - end: /\bFROM\b/, - returnEnd: true, - //scope: 'clause: select', - keywords: SOQL_SPECIAL_WORDS, - contains: [ - PUNCTUATION_COMMA, - { - match: [/(?=[\s\,])/, APEX_IDENT_RE, /(?=[\s\,])/], - scope: { 2: 'subst' } - } // * back to main text color - ] + const SOQL_DATE_LITERALS_SIMPLE = { + match: /\b(TODAY|TOMORROW|YESTERDAY)\b/, + scope: 'keyword' }; - const SOQL_DATE_LITERALS = { + const SOQL_DATE_LITERALS_COMPLEX = { match: /(NEXT|LAST|THIS)_(90_DAY|DAY|FISCAL_QUARTER|FISCAL_YEAR|MONTH|QUARTER|WEEK|YEAR)S?\b/, scope: 'keyword', @@ -999,6 +940,11 @@ export default function (hljs) { }, relevance: 8 }; + const SOQL_DATE_LITERALS = [ + SOQL_DATE_LITERALS_SIMPLE, + SOQL_DATE_LITERALS_COMPLEX, + SOQL_DATE_LITERALS_W_PARAMS + ]; const SOQL_QUERY = { begin: [/\[/, /\s*(?=(SELECT|FIND)\b)/], @@ -1008,9 +954,11 @@ export default function (hljs) { scope: 'soql', relevance: 10, endsWithParent: true, - keywords: SOQL_SPECIAL_WORDS, + keywords: { + literal: KEYWORDS.literal, + built_in: BUILT_INS + }, contains: [ - SOQL_SELECT, NUMBERS, OPERATORS, STRINGS, @@ -1025,14 +973,39 @@ export default function (hljs) { //returnEnd: true, contains: [{ match: APEX_IDENT_RE, scope: 'type' }, ...DOT_NOTATION] }, - SOQL_DATE_LITERALS, - SOQL_DATE_LITERALS_W_PARAMS, { + match: regex.concat( + /\b/, + regex.either(...SOQL_DATE_SELECT_FUNCTIONS, ...SOQL_FUNCTIONS), + /\b/ + ), + scope: 'title.function' + }, + { + match: /\b(GROUP|ORDER)\s+BY\b/, + scope: 'title.function' + }, + ...SOQL_DATE_LITERALS, + { + match: regex.concat( + /\b/, + regex.either( + ...KEYWORDS.keyword, + ...SOQL_KEYWORDS, + ...SOQL_OPERATORS + ), + /\b/ + ), + scope: 'keyword' + }, + { + // colon notation match: [/(?<=:)/, /\s*/, APEX_IDENT_WORD_RE, /(?!\()/], scope: { 3: 'variable' }, relevance: 0 }, { + // any non-soql function used in the query match: [/(?<=:|\.)/, APEX_IDENT_RE, /(?=\s*\()/], scope: { 2: 'title.function.invoke' }, relevance: 0 diff --git a/test/markup/apex/apexcode.expected.txt b/test/markup/apex/apexcode.expected.txt index ca1ac9e..cdc77ad 100644 --- a/test/markup/apex/apexcode.expected.txt +++ b/test/markup/apex/apexcode.expected.txt @@ -2,7 +2,7 @@ * @author John Smith */ @IsTest(Seealldata=true) -public with sharing class L2Char implements Database.batchable { +public with sharing class L2Char implements Database.batchable { public static final String ERROR = 0x0001; @InvocableMethod(label='my invocable') @@ -22,27 +22,27 @@ Database.insert(myAccounts, false); } } -} -@TestSetup -private static void makeData(Boolean a){ - Custom__c c = new Custom__c(); - - for(Account a : acctLis ){ - ConnectApi.insert a; + @TestSetup + private static void makeData(Boolean a){ + Custom__c c = new Custom__c(); + + for(Account a : acctLis ){ + ConnectApi.insert a; + } } -} -@isTest -private static void testme(){ - System.assert(true); -} + @isTest + private static void testme(){ + System.assert(true); + } -@testVisible -private List<SelectOption> recordTypes { get; private set; } + @testVisible + private List<SelectOption> recordTypes { get; private set; } -for(Account a : [SELECT Id FROM Account WHERE LastModifiedDate = LAST_N_DAYS:3]){ - Assert.fail(); + for(Account a : [SELECT Id FROM Account WHERE LastModifiedDate = LAST_N_DAYS:3]){ + Assert.fail(); + } } trigger CTrig on Custom__c (before insert){