当前位置: 首页 > news >正文

企业网站建设费入什么科目线上推广渠道有哪些

企业网站建设费入什么科目,线上推广渠道有哪些,网站外链建设教程,网投网站怎样建目标#xff1a; 对于项目中的静态方法#xff08;主要是各种工具类里的静态方法#xff09;#xff0c;可以在输入方法名时直接提示相关的静态方法#xff0c;选中后自动补全代码#xff0c;并导入静态类。 设计#xff1a; 初步构想#xff0c;用户选择要导入的文…目标 对于项目中的静态方法主要是各种工具类里的静态方法可以在输入方法名时直接提示相关的静态方法选中后自动补全代码并导入静态类。 设计 初步构想用户选择要导入的文件夹遍历文件夹下面文件的静态方法并存储当用户输入时使用弹窗显示候选方法选中后补全代码。 分解步骤为 在设置页加入视图化操作让用户选择文件夹路径通过持久化数据将选择的文件夹路径保存到本地IDE打开时遍历本地保存的文件夹路径下的所有文件得到所有静态方法用户输入时弹窗显示联想方法选中后自动补全 开发 1.搭建开发环境 JetBrains已经提供了纯样板模板我们下载提供的插件模板 使用Android Studio 或IntelliJ IDEA 打开后可以在gradle.properties中修改项目的属性gradle.gradle.properties里各属性表示的意义如下 gradle.properties配置 pluginGroup、pluginName_、pluginVersion插件名称与版本 pluginSinceBuild、pluginUntilBuild插件适用的IDE版本从since到until各种IDE的版本号可以在这个地方查阅内部编号范围 Android Studio对应的IntelliJ 平台版本可以查阅Android Studio pluginVerifierIdeVersions用来检查IDE版本和插件之间兼容性 **platformType**插件适用的IDE类型IC指社区版Android Studio基于社区版修改 platformPlugins 声明插件依赖项 更多的属性可以查阅此链接 https://github.com/JetBrains/intellij-platform-plugin-template https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties plugin.xml 文件位于src\main\resources\META-INF下 idgradle.properties里的pluginName_ name gradle.properties里的pluginName_ vendor开发者的名字 添加依赖 build.gradle.kts 在intellij节点下加入一句intellij alternativeIdePath H:\Android\Android Studio路径设置为本地Android Studio位置这样在运行时会直接使用本地的AS调试避免重新下载Android Studio。 settings.gradle.kts 修改项目名称 rootProject.name Plugin Template Hint配置完成后点击右边的gradle的runide即可运行插件,如果开发过程中想进行调试可以右键选择debug模式。 2.设置页添加视图化操作 在IDE的设置页添加新UI需要使用applicationConfigurable Extension Points。 先在plugin.xml里注册applicationConfigurable并且新建类继承Configurable。插件的UI模块是在java的swing组件基础上直接包装了一层可以直接使用。 extensions defaultExtensionNscom.intellij......applicationConfigurable instancecom.plugin.hint.other.UtilsImportUI //extensionsclass UtilsImportUI : Configurable {private val persistentState: UtilsFolderSetting ApplicationManager.getApplication().getComponent(UtilsFolderSetting::class.java)private var isModify false//绘制界面使用Swing组件override fun createComponent(): JComponent? {//......绘制代码此处省略}//控制按钮“Apply”是否可点击override fun isModified(): Boolean {return isModify}//Apply按钮点击事件override fun apply() {......persistentState!!.list pathListpersistentState.loadState(persistentState)//持久化数据isModify false }//配置面板左边窗口的显示名称override fun getDisplayName(): String {return Import Utils Files}//调用IDE的文件管理器选择文件private fun dir(jPanel: JPanel): String {if (project null) {project guessCurrentProject(jPanel)}val fcDial FileChooserFactory.getInstance().createFileChooser(fcDesc, project, null)val files fcDial.choose(project)return if (files.isNotEmpty()) {files[0].path} else } }上面省略了部分代码主要是绘制界面、持久化数据、保存用户选中的文件位置并进行相关的去重。 效果如下 3.持久化数据 为了保存用户选择的文件夹路径我们需要对数据进行持久化。 在plugin.xml里注册implementation-class并且新建类继承PersistentStateComponent其中name为XML中根标记的名称storages 为保存的文件的名称默认位置是配置文件地址的options目录下默认位置可以点击File - Mange IDE Settings - Export Settings 查看。 我们将路径通过list保存读取时 application-componentscomponentimplementation-classcom.plugin.hint.other.UtilsFolderSetting/implementation-class/component/application-componentsState(name searchUtilsPath, storages [Storage(value searchUtilsPath.xml)]) class UtilsFolderSetting : PersistentStateComponentUtilsFolderSetting? {var list: MutableListString ArrayList()override fun getState(): UtilsFolderSetting {return this}override fun loadState(state: UtilsFolderSetting) {XmlSerializerUtil.copyBean(state, this)} }4.启动时遍历文件保存静态方法 工程模板service下有两个类MyApplicationService和MyProjectService分别是 application 级别的service和 project 级别的service其实还有一个module 级别的service但是并不推荐性能原因。其中MyApplicationService为全局单例而MyProjectService会在对应范围的每个实例创建一个单独的服务实例。这里我们在MyProjectService里遍历文件夹路径对所有文件进行解析并保存静态方法。 class MyProjectService(project: Project) {init {if (project.workspaceFile ! null) {val persistentState ApplicationManager.getApplication().getComponent(UtilsFolderSetting::class.java)val pathList persistentState.list//得到持久化数据for (s in pathList) {//遍历文件夹路径UtilMethodsHandle.addPsiMethodByPath(s, project)}}} }persistentState 为得到的持久化数据然后再对文件路径进行解析。 addPsiMethodByPath方法如下逻辑可以看注释 var globalPsiMethods HashMapString, ListPsiMethod()//遍历文件夹解析文件存储方法fun addPsiMethodByPath(path: String, project: Project) {val virtualFile project.workspaceFile!!.fileSystem.findFileByPath(path) ?: returnif (virtualFile.isDirectory) {//如果是文件夹递归遍历val virtualFiles virtualFile.childrenfor (file in virtualFiles) {addPsiMethodByPath(file.path, project)}} else {//如果是文件解析val psiFile PsiManager.getInstance(project).findFile(virtualFile)//判断是否是java文件后面看是否支持kotlin文件if (psiFile is PsiJavaFile) {val classes psiFile.classes //遍历文件里的类因为可能会有内部类for (aClass in classes) {val tempMethods aClass.methodsval list: MutableListPsiMethod ArrayList()//遍历类里面的方法for (method in tempMethods) {//判断是静态并且不是私有的方法if (method.hasModifierProperty(PsiModifier.STATIC) !method.hasModifierProperty(PsiModifier.PRIVATE)) {list.add(method)}}globalPsiMethods[path] list}}}}解释上面的代码需要先了解IntelliJ平台的一些名称概念。 PSI 程序结构接口(Program Structure Interface)是IntelliJ平台中的一个层负责解析文件并创建支持平台许多功能的语法和语义代码模型。 PSI File IDEA将文件结构抽象为接口叫程序结构接口文件(PSI File)不同类型的文件解析后生成不同的PsiFile接口的实现类实例这也是IDEA能够扩展支持多语言的基础。PsiFile类是所有PSI文件的公共基类而在特定的语言文件通常是由它的子类来表示。例如PsiJavaFile类表示Java文件XmlFile类表示XML文件。 VirtualFileSystem 虚拟文件系统VFS是IntelliJ平台的组件该组件封装了用于处理以Virtual File表示的文件的大部分活动。 它具有以下主要目的 提供一个通用API来处理文件而不管文件的实际位置如何在磁盘上在归档中在HTTP服务器等上 当检测到更改时跟踪文件修改并提供文件内容的旧版本和新版本。 提供了将其他持久性数据与VFS中的文件相关联的可能性。 Virtual File System 上面的代码通过project得到VirtualFile,判断如果是文件夹递归调用方法否则返回相对应的PsiFile接着判断如果是PsiJavaFile因为项目有可能包含kotlin文件,则遍历PsiClass有可能包含内部类得到所有PsiMethod最后判断method是否是静态的method.hasModifierProperty(PsiModifier.STATIC)并且不是私有的!method.hasModifierProperty(PsiModifier.PRIVATE)最后加入列表。 5.用户输入时自动弹窗显示联想方法 这里的两种方案其实最开始使用的是第一种方法在IDE自带的代码补全弹窗里插入我们保存的方法但是这种方案没有解决方法显示排序的问题提供的 orderfirst属性并没有生效最后使用了第二种方案。这里记录一下可能以后在写其他插件时会用到。 第一种方案 我们在plugin.xml里注册CompletionContributor language为JAVA extensions defaultExtensionNscom.intellij......completion.contributorimplementationClasscom.plugin.hint.other.UtilsCompletionContributor languageJAVAorderfirst //extensionsCompletionContributor实现extend函数有三个参数 CompletionType代码完成的类型基本完成BASIC、智能类型SMART匹配完成Settings/Preferences | Editor | General | Code Completion里可选. ElementPattern匹配类型可以对返回的元素进行过滤CompletionProvider内容提供者我们在这里返回待选择的 class UtilsCompletionContributor : CompletionContributor() {//查找可以自动补全的代码init {extend(CompletionType.BASIC, PlatformPatterns.psiElement(), UtilsCompletionProvider())} }UtilsCompletionProvider类继承CompletionProvider重写addCompletions方法将元素加入到CompletionResultSet。 class UtilsCompletionProvider : CompletionProviderCompletionParameters() {//添加自动补全代码override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {val prefix result.prefixMatcher.prefixif (prefix.isEmpty()) {return}for (methodList in UtilMethodsHandle.globalPsiMethods.values) {for (method in methodList) {var s: String? if (method.containingClass ! null) {s method.containingClass!!.qualifiedName//类名称}val element: LookupElement LookupElementBuilder.create(method).withTypeText(s)//右边文字//.withIcon(MethodIcon).withIcon(AllIcons.Nodes.MethodReference)//左边图标.withBoldness(true)//是否加粗//选中后的处理事件.withInsertHandler { context1: InsertionContext, lookupElement: LookupElement? -context1.document.insertString(context1.startOffset, .)context1.document.insertString(context1.tailOffset, ();)//导入所引用的类JavaCompletionUtil.insertClassReference(method.containingClass!!, context1.file, context1.startOffset)//移动光标到代码尾部 context1.editor.caretModel.moveToOffset(context1.tailOffset - 2)}//添加element到代码补全弹窗result.addElement(PrioritizedLookupElement.withPriority(element, Int.MAX_VALUE.toDouble()))}}上面代码先检测是否有匹配的否则返回。然后循环创建LookupElement。InsertHandler为选中后的操作在这里补全代码引入当前方法所在类。 如上图在自带的代码补全弹窗里添加了2条我们的方法。 第二种方案 在用户输入后使用快捷键呼出代码补全弹窗使用Action完成。IntelliJ 平台中的Action需要代码实现并且必须注册。注册决定了Action在 IDE UI 中出现的位置。实现并注册后Action会接收来自 IntelliJ 平台的回调以响应用户。 1.创建UtilsAction类继承 Action类。当使用键盘快捷键或从菜单、工具栏操作时就会回调 Action 类的 actionPerformed 方法。 先在plugin.xml里注册Action这里默认的快捷键是control shift X actionsaction classcom.plugin.hint.other.UtilsAction description方法提示 idplugin.hint texthintadd-to-group anchorfirst group-idCodeCompletionGroup /keyboard-shortcut first-keystrokecontrol shift X keymap$default //action/actions效果如图Code Completion组下添加了我们新建的Action在这里也可以更改快捷键。 在UtilsAction类里我们在actionPerformed 方法里弹出代码补全弹窗。searchText为用户输入的需要补全的代码。LookupImpl为为代码补全的弹窗。选中逻辑与第一种方案一样。 class UtilsAction : AnAction() {override fun actionPerformed(e: AnActionEvent) {......//需要查找的字符val searchText StringBuilder()//selectedText表示光标选中的文本如果不为空则查找选中的没有就从光标位置向前拼接字符一直到空格为止if (editor.selectionModel.selectedText null|| editor.selectionModel.selectedText ) {var indexText document.text.subSequence(startOffset - 1, startOffset).toString()while (startOffset 0 nameMatch(indexText)) {searchText.insert(0, indexText)startOffset--indexText document.text.subSequence(startOffset - 1, startOffset).toString()}} else {searchText.append(editor.selectionModel.selectedText)}if (project ! null) {val lookup obtainLookup(editor, project)for (methodList in UtilMethodsHandle.globalPsiMethods.values) {for (method in methodList) {var qualifiedName: String? if (method.containingClass ! null) {qualifiedName method.containingClass!!.qualifiedName}LOG.info(actionPerformed: $method$qualifiedName)if (!method.isValid) continue//检查元素是否有效比如切换分支后就会失效//创建一个element与第一种方案一样val element: LookupElement LookupElementBuilder.create(method).withTypeText(qualifiedName).withIcon(MethodIcon)//.withIcon(AllIcons.Nodes.MethodReference).withBoldness(true)val item CompletionResult.wrap(element, PlainPrefixMatcher(searchText.toString()), CompletionSorter.emptySorter())if (item ! null) {//将element添加进去lookup.addItem(item.lookupElement, item.prefixMatcher)}}}lookup.addLookupListener(object : LookupListener {override fun itemSelected(event: LookupEvent) {//item选中事件与val lookupElement event.item as LookupElementif (lookupElement.psiElement is PsiMethod) {//如果选中的element是方法val psiMethod lookupElement.psiElement as PsiMethod//得到上下文InsertionContextval insertionContext InsertionContext(OffsetMap(document), Lookup.AUTO_INSERT_SELECT_CHAR, arrayOf(lookupElement), psiFile!!, editor, false)//val tailOffset OffsetMap(document).getOffset(InsertionContext.TAIL_OFFSET)//如果是选中状态计算开始位置需要减去字符长度if (startOffset start) startOffset - searchText.lengthdocument.insertString(startOffset, .)document.insertString(insertionContext.tailOffset, ();)//导入所引用的类JavaCompletionUtil.insertClassReference(psiMethod.containingClass!!, psiFile, startOffset)//移动光标到代码尾部editor.caretModel.moveToOffset(insertionContext.tailOffset - 2)}}})lookup.showLookup()//显示弹窗}private fun obtainLookup(editor: Editor, project: Project): LookupImpl {val lookup LookupManager.getInstance(project).createLookup(editor, LookupElement.EMPTY_ARRAY, ,DefaultArranger()) as LookupImpl/* if (editor.isOneLineMode) {lookup.setCancelOnClickOutside(true)lookup.setCancelOnOtherWindowOpen(true)}*///lookup.lookupFocusDegree if (autopopup) LookupFocusDegree.UNFOCUSED else LookupFocusDegree.FOCUSEDreturn lookup}}这里使用的代码补全弹窗是系统自带的弹窗在这里说一下怎么找到各种UI相对应的类。 我们需要启用内部模式。在idea.properties里添加idea.is.internaltrue保存并重启IDE。会看到Tool中多了一个选项Internal Actions然后选择 UI - UI Inspector,打开 UI 检查器启用之后就可以以交互方式测试UI元素。查看时将光标居中于UI元素上使用CtrlAlt鼠标左键即可显示UI元素的内部描述.。 效果如图可以看到相关的类然后就可以再去找到具体的实现方法。 最终效果如下 在这里插入图片描述 相关资料 IntelliJ Platform SDK 使用PSI分析Java代码 Intellij IDEA 插件开发秘籍
http://www.yingshimen.cn/news/53499/

相关文章:

  • 烟台网站定制排名设计制作数字电压表
  • 做网站都有跳转链接做网站什么系统简单
  • 上海市城乡建设管理局网站360免费建站不要钱
  • 使用cms建设网站安全吗网站建设全程揭秘光盘文件
  • 不需要备案的服务器seo公司发展前景
  • html做的网站wordpress 数据库爆炸
  • 网页设计网站的主题济南软件开发培训机构
  • 重庆建设厂网站潮州市住房和城乡建设局网站
  • 有网站源码怎么上传南京市建设行政网站
  • gucci网站dnn wordpress
  • 男装商城网站建设wordpress 租赁主题
  • 公司网站怎么做关键词上海医院设计网站建设
  • 营销型网站的建设和运营网站 改版 方案
  • 网站app有哪些功能电商兼职网站开发
  • 淘宝客网站主机wordpress软件企业主题
  • 上海做网站好的公司有哪些网页设计培训机构哪个好
  • 专门做投标书的网站怎么看一个网站是谁做的
  • 建立个人博客网站wordpress月子会所网站建设方案
  • 杭州信贷网站制作wordpress分类目录最简化404
  • 外贸流程有哪些北京seo公司有哪些
  • 做电子商务网站需要什么手续戴尔网站建设的特点
  • 如何自建外贸网站营销推广的形式包括
  • wordpress建售卖产品的网站如何让网站免费
  • 医院网站做品牌推广需要哪些怎么去做推广
  • 学徒制下的课程网站建设曹县有没有做网站
  • 内部网站做域名解析到端口外包app制作费用多少
  • 外贸网站推广销售wordpress 视频自适应插件
  • 网站建设第三方欧洲网站服务器
  • 鲜花网站的网络营销与策划书深圳网站制作作
  • 东阿网站制作wordpress搬家需要修改